重返现世

III.重返现世

考虑扩展minmax定理:

Kthmax(S)=TS(1)|T|K(|T|1K1)min(T)

因为本题方便求的是 min(T),但是要求的却是 Kthmin,所以我们不妨翻转 K 变成 Kthmax。并且,注意到有一行 nk10,故翻转后亦有 K10

现在,考虑 min(T) 应该怎么求。显然,其就是抽到任意 T 中元素的期望时间,即 miTai

但是,明显我们不能枚举所有 T,因为 n 过大。但是,注意到 m 很小,故我们可以将 m 带进DP状态里。又因为那个不知道有啥用的 K 也很小,所以我们考虑将它也带进状态。

于是我们设计了这样的状态:fk,i,j 表示 K=k,当前考虑了前 i 个数,且 iTai=j 时,TS(1)|T|K(|T|1K1) 之和。

现在,考虑 ai 选还是不选。如果不选,显然有 fk,i,jfk,i1,j

那如果选呢?我们考虑由 fk,i1,j 转移到 fk,i,j+ai。在前面的式子中,仅有 |T| 一项产生了变化。(1)|T|K 这项随着 |T| 加一取反了,而 (|T|1K1) 这项呢?

依照二项式系数的递推公式,我们有 (|T|1K1)=(|T|2K1)+(|T|2K2)。这意味着,TS(1)|T|K(|T|1K1)=TS(1)|T|K(|T|2K1)+TS(1)|T|K(|T|2K2)(注意到仅有前面是个减号,因为 K2 这项需要取两次反,等于没取,而前面这项取一次反),即 fk,i,jfk1,i1,jaifk,i1,jai

明显是背包的样式,故 i 这维可以压掉。

关键是初始状态。事实上,f0,0,0=0,对于非零的 kfk,0,0=1,这个奇奇怪怪的边界被证明是正确的。具体可以通过反推得出。

时间复杂度 O(nmk)

代码:

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int ksm(int x,int y=mod-2){int z=1;for(;y;y>>=1,x=1ll*x*x%mod)if(y&1)z=1ll*z*x%mod;return z;}
int n,m,K,a[1010],f[11][10100],res;
int main(){
	scanf("%d%d%d",&n,&K,&m),K=n-K+1;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int k=1;k<=K;k++)f[k][0]=mod-1;
	for(int i=1;i<=n;i++)for(int k=K;k;k--)for(int j=m;j>=a[i];j--)(f[k][j]+=(f[k-1][j-a[i]]-f[k][j-a[i]]+mod)%mod)%=mod;
	for(int i=1;i<=m;i++)(res+=1ll*f[K][i]*ksm(i)%mod)%=mod;
	printf("%d\n",1ll*res*m%mod);
	return 0;
}

posted @   Troverld  阅读(58)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示