题解:P14636 [NOIP2025] 清仓甩卖 / sale
happy_zero · · 题解
以此篇题解记录我失败的 NOIP。这凭啥有紫啊,还有和范德蒙德等式有啥关系。
考虑不优的情况,一种是可以把最小的两个
先将
发现
而对于第二种情况相当于选了一个
笑点(这并不好笑)解析:考场上想冲正解所以没有枚举
代码过民间数据了,就先放上来了。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e4 + 5;
const int P = 998244353;
int a[N], fac[N], inv[N], pw[N];
inline int qpow(int a, int b = P - 2) {
int res = 1;
while (b) {
if (b & 1) res = res * a % P;
a = a * a % P, b >>= 1;
} return res;
}
inline void init() {
pw[0] =fac[0] = inv[0] = 1;
for (int i = 1; i < N; i++)
pw[i] = pw[i - 1] * 2 % P, fac[i] = fac[i - 1] * i % P;
inv[N - 1] = qpow(fac[N - 1]);
for (int i = N - 2; i; i--)
inv[i] = inv[i + 1] * (i + 1) % P;
}
inline int C(int n, int m) {
if (n < 0 || m < 0 || n < m) return 0;
return fac[n] * inv[m] % P * inv[n - m] % P;
}
inline void solve() {
int n, m; cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + 1 + n); int ans = pw[n];
for (int i = 1; i <= n; i++)
for (int j = i + 1, x = 0; j <= n && a[i] +a[i] > a[j]; j++) {
while (x <= i && a[x + 1] + a[i] < a[j]) x++;
if (x >= i) break; if (a[j] == a[i]) continue;
ans = (ans - pw[x] * C(n - i - 1, m - 2 - n + j) % P + P) % P;
}
cout << ans << '\n';
}
signed main() {
freopen("sale.in","r",stdin);
freopen("sale.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
init(); int c, T; cin >> c >> T;
while (T--) solve();
return 0;
}