[NOIP2025] 清仓甩卖 / sale
lovely_nst · · 题解
考虑算不合法的情况。显然是买了
考虑对这个计数,首先对
因此要满足
考虑分讨:
-
对于
p>k ,此时无论w 为啥,p 的性价比均高于k ,这样的p 有n-k 个,w=1 时花费1 ,w=2 时花费2 。 -
对于
i<p<k ,当w=1 时性价比更高,反之更低,因此当w=1 时花费1 ,而w=2 时选不到,因此花费0 。 -
对于
\dfrac{a_k}2<a_p<a_i ,若此时w=1 ,a_p+a_i 一定大于a_k ,显然无解。因此只可能w=2 ,性价比更低,选不到,因此花费0 。
以上情况在贡献全部加完后会剩余
剩下的情况,就是找到最大满足
因此方案数为
AC Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5005 , M = 10005 , mod = 998244353;
int cid , T;
int n , m;
int a[N] , fr[M] , inv[M] , pw[M];
int power (int x , int y)
{
int mul = 1;
while (y)
{
if (y & 1) mul = mul * x % mod;
x = x * x % mod;
y >>= 1;
}
return mul;
}
int C (int x , int y)
{
if (x < y) return 0;
return fr[x] * inv[y] % mod * inv[x - y] % mod;
}
void Add (int &x , int y)
{
x += y;
if (x >= mod) x -= mod;
}
signed main ()
{
fr[0] = inv[0] = pw[0] = 1;
for (int i = 1;i < M;i ++) fr[i] = fr[i - 1] * i % mod , pw[i] = (pw[i - 1] << 1) % mod;
inv[M - 1] = power (fr[M - 1] , mod - 2);
for (int i = M - 2;i >= 1;i --) inv[i] = inv[i + 1] * (i + 1) % mod;
ios::sync_with_stdio (0);
cin.tie (0) , cout.tie (0);
cin >> cid >> T;
while (T --)
{
cin >> n >> m;
for (int i = 1;i <= n;i ++)
cin >> a[i];
sort (a + 1 , a + n + 1);
int ans = 0;
for (int i = 1;i <= n;i ++) // w_i = 1
{
int p = 0;
for (int j = i + 1;j <= n;j ++) if (a[i] < a[j] && a[j] < (a[i] << 1)) // w_j = 2
{
// k > j : n - j (1 / 2)
// i < k < j : j - i - 1 (0 / 1)
// sum = m - 2
int s1 = n - j , s2 = j - i - 1;
if (m - 2 - s1 < 0) continue;
// a_p + a_i < a_j
while (p < n && a[p + 1] + a[i] < a[j])
p ++;
int w = C (n - i - 1 , m - 2 - (n - j));
Add (ans , pw[p] * w % mod);
}
}
cout << (pw[n] - ans + mod) % mod << '\n';
}
return 0;
}