重返现世
III.重返现世
考虑扩展minmax定理:
因为本题方便求的是 ,但是要求的却是 ,所以我们不妨翻转 变成 。并且,注意到有一行 ,故翻转后亦有 。
现在,考虑 应该怎么求。显然,其就是抽到任意 中元素的期望时间,即 。
但是,明显我们不能枚举所有 ,因为 过大。但是,注意到 很小,故我们可以将 带进DP状态里。又因为那个不知道有啥用的 也很小,所以我们考虑将它也带进状态。
于是我们设计了这样的状态: 表示 ,当前考虑了前 个数,且 时, 之和。
现在,考虑 选还是不选。如果不选,显然有 。
那如果选呢?我们考虑由 转移到 。在前面的式子中,仅有 一项产生了变化。 这项随着 加一取反了,而 这项呢?
依照二项式系数的递推公式,我们有 。这意味着,(注意到仅有前面是个减号,因为 这项需要取两次反,等于没取,而前面这项取一次反),即 。
明显是背包的样式,故 这维可以压掉。
关键是初始状态。事实上,,对于非零的 令 ,这个奇奇怪怪的边界被证明是正确的。具体可以通过反推得出。
时间复杂度 。
代码:
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?