NOIP2025 T2 题解
场上心态崩溃,无法 debug,被这题送退役了。
这种题,要计数,显然需要先会判定一个方案是否合法。而且一般合法条件非常强,不然没办法计数。以下讨论一个方案不合法的条件。
首先可以将
考虑把原序列
容易证明,不管是性价比策略,还是实际最优策略,
设
如果按照性价比排序的策略买,则应该满足
如果是原价最大的策略,那么应该是
当
所以,一种方案不合法,即按照性价比策略取不到最优解,等价于以下不等式:
现在可以开始计数了,暴力枚举
代入
而注意到
有一个重要的细节,
最后答案即为
时间复杂度
~去掉头文件和组合数预处理总共就十行,不知道场上在调什么鬼。~
::::success[代码]
#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define ve vector<ll>
#define fi first
#define se second
#define pb push_back
#define mid (l+r>>1)
#define lx (x<<1)
#define rx (x<<1|1)
using namespace std;
const ll N=5008,P=998244353;
ll T,n,m,ans,a[N],pw[N],c[N][N];
void init(){
pw[0]=1;
for(ll i=1;i<N;i++)pw[i]=pw[i-1]*2%P;
for(ll i=0;i<N;i++)
for(ll j=0;j<=i;j++)
c[i][j]=(j?c[i-1][j]+c[i-1][j-1]:1)%P;
}
void slv(){
cin>>n>>m,a[n+1]=ans=0;
for(ll i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+n+1,greater<ll>());
for(ll j=2;j<=n;j++){
ll p=j+1,s=0;
for(ll i=j+1;i<=n+1;i++)
(s+=pw[max(n-i,0ll)])%=P;
for(ll k=max(m-j,0ll)+1;k<min(j,m);k++)
if(a[k]<2*a[j]){
while(p<=n+1&&a[p]>=a[k]-a[j])
(s-=pw[max(n-p,0ll)])%=P,p++;
(ans+=c[j-2][m-k-1]*s)%=P;
}
}
cout<<(pw[n]-ans+P)%P<<'\n';
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>T>>T,init();
while(T--)slv();
return 0;
}
::::