洛谷P5131 荷取融合

题目

https://www.luogu.com.cn/problem/P5131

思路

刚开始看到这道题以为是一个经典的移项求DP方程的概率DP题,也就是说每一步过程都是随机转移,后来发现理解错了题意。。。

观察一下样例珂以发现,题目的意思实际是说:每一个合法的抓取序列出现的概率是相同的。所以我们只要求出所有合法序列的总贡献除以合法序列的总数即可。

我们设开头为i,长度为j的序列的总贡献为f(i,j),则有f(i,j)=a[i]k=inf(k,j1)

注意到这个递推式只和上一层的状态有关,所以我们珂以像背包问题一样采取合适的枚举顺序优化一维空间。

这个 其实就是一个后缀和,不影响复杂度。

那么接下来就是求合法序列的总数(假定为 m ),注意到机械臂只能不动或向右,相当于固定顺序,所以是一个组合问题,又因为珂以不动,所以是一个可重集组合问题。

m=(n+k1n1)(这个模型很经典,珂以构造母函数也珂以利用组合意义隔板法解决)。

最终答案是m1i=1nf(i,k)

算法时间复杂度Θ(nk),空间复杂度Θ(n+k)

代码

点击查看代码
#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;
}
posted @   文艺平衡树  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示