洛谷P5131 荷取融合
题目
https://www.luogu.com.cn/problem/P5131
思路
刚开始看到这道题以为是一个经典的移项求DP方程的概率DP题,也就是说每一步过程都是随机转移,后来发现理解错了题意。。。
观察一下样例珂以发现,题目的意思实际是说:每一个合法的抓取序列出现的概率是相同的。所以我们只要求出所有合法序列的总贡献除以合法序列的总数即可。
我们设开头为,长度为的序列的总贡献为,则有
注意到这个递推式只和上一层的状态有关,所以我们珂以像背包问题一样采取合适的枚举顺序优化一维空间。
这个 其实就是一个后缀和,不影响复杂度。
那么接下来就是求合法序列的总数(假定为 ),注意到机械臂只能不动或向右,相当于固定顺序,所以是一个组合问题,又因为珂以不动,所以是一个可重集组合问题。
(这个模型很经典,珂以构造母函数也珂以利用组合意义隔板法解决)。
最终答案是
算法时间复杂度,空间复杂度
代码
点击查看代码
#include<cstdio>
#include<cstdlib>
#define mod 19260817
#define maxn 120000
#define ll long long
using namespace std;
ll a[maxn];
ll dp[maxn],fac[maxn];
ll qpow(ll x,int p){
ll ans=1,base=x;
for(;p;p>>=1){
if(p&1) ans=ans*base%mod;
base=base*base%mod;
}
return ans;
}
ll inv(ll x){
return qpow(x,mod-2);
}
int main(){
int n,k,i,j;
ll ans=0,m=0;
scanf("%d%d",&n,&k);
for(i=1;i<=n;++i) scanf("%lld",&a[i]);
fac[0]=1;
for(i=1;i<=n+k;++i) fac[i]=fac[i-1]*i%mod;
for(i=1;i<=n;++i) dp[i]=a[i];
for(i=2;i<=k;++i){
ll sum=0;
for(j=n;j>=1;--j){
sum=(sum+dp[j])%mod;
dp[j]=sum*a[j]%mod;
}
}
for(i=1;i<=n;++i) ans=(ans+dp[i])%mod;
m=(fac[n+k-1]*inv(fac[k])%mod)*inv(fac[n-1])%mod;
printf("%lld",ans*inv(m)%mod);
// system("pause");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具