1 条题解
-
0
过了所有大样例和洛谷数据。虽然 4h 才切,但也算是一雪前耻了。
:::info[Hint]{open} 正难则反,取不到最大原价总和只有两种情况:
-
最优解选性价比较低的 ,小 R 选性价比较高的 ,且 的原价低于 的原价。
-
最优解选性价比中的 ,小 R 选性价比较高的 和性价比较低的 ,且两个 的原价之和低于 的原价。
上述的 是最优解中选取的性价比最低的 ,上述的 是小 R 选取的性价比最低的 。
性价比高于所选性价比最低的 的 都必选,性价比高于所选性价比最低的 的 都必选。 :::
:::info[Tip] 一个组合意义显然成立的恒等式:
$$\sum_{i=0}^{k}\dbinom{n}{i}\dbinom{m}{k-i}=\dbinom{n+m}{k}$$:::
按原价从大到小排序,枚举:(记 为 中 的数量)
- 对于第一种情况,枚举最优解的 (记为 )以及小 R 的 (记为 ),则 ,则方案数为:
:::info[分析] 最优解选了 中的所有、、 中的 。
小 R 选了 中的所有、 中的 、。 :::
- 对于第二种情况,枚举最优解的 (记为 )以及小 R 的性价比较高的 (记为 ),则 ,设 为使得 (即可以成为性价比较低的 )的最小的 ,则方案数为:
:::info[分析] 最优解选了 中的所有、、 中的 。
小 R 选了 中的所有、 中的 、、。 :::
于是在 一定时,二种情况的方案数之和就是:
使用双指针维护即可。
时间复杂度 ,空间复杂度 或 。
:::success[[NOIP2025] 清仓甩卖 - sale.cpp]
#include<bits/stdc++.h> using namespace std; const int maxn=5010; const int mod=998244353; int dp[maxn][maxn],pre[maxn],a[maxn]; int main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); dp[0][0]=pre[0]=1; for(int i=1;i<=maxn-10;i++){ dp[i][0]=1; pre[i]=pre[i-1]<<1; if(pre[i]>=mod) pre[i]-=mod; for(int j=1;j<=i;j++){ dp[i][j]=dp[i-1][j]+dp[i-1][j-1]; if(dp[i][j]>=mod) dp[i][j]-=mod; } } int c,t;cin>>c>>t; while(t--){ int n,m;cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i]; sort(a+1,a+1+n,greater<int>()); long long ans=0; for(int i=1;i<=n;i++){ if(m-i-1<0) break; int p=n+1; for(int j=max(i+1,m-i+1);j<=n;j++){ if(a[i]==a[j]) continue; if(a[i]>=(a[j]<<1)) break; while(p>1 and a[p-1]+a[j]<a[i]) p--; ans+=1ll*dp[j-2][m-i-1]*pre[n-p+1]%mod; } } cout<<(pre[n]-ans%mod+mod)%mod<<"\n"; } return 0; }:::
-
- 1
信息
- ID
- 1921
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 10
- 标签
- 递交数
- 14
- 已通过
- 1
- 上传者