P5131 荷取融合 —— DP

题意

n 个正整数构成的序列 ai,进行如下 k 次操作:

  • posxx[pos,n] ) 。 然后将 pos 加入 Aposx 均为为正整数且 pos 初始为1,A 初始为空集)。

ans=jAaj,求 ans 的期望。

分析

观察数据范围:n105,k300

结合时限1s,我们只能接受时间复杂度为 O(nk) 的算法。

考虑状态设计: fi,jgi,j 表示在 j 次操作后 pos=i 时的权值积之和与操作方案数。

那么 fi,jfi,j1 转移而来:

fi,j=w=1ifw,j1aw

gi,jgi,j1 转移而来:

gi,j=w=1igw,j1

记录 fi,j1gi,j1 的前缀和,在处理到 fi,jgi,j 时就可以直接计算。

再观察空间限制:125MB。

因为当前状态只由上一次选择转移而来,所以用滚动数组优化。

ans1=i=1nfi,kans2=i=1ngi,kans=ans1ans2(mod 19260817)

注意取模,求逆元即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+100,K=3e2+10;
const ll mod=19260817;
int n,k;
ll f[N][2],g[N][2],h[N];
ll qc(ll a, ll b)
{
ll sum=1;
while(b)
{
if(b&1)
sum=sum*a%mod;
a=a*a%mod;
b>>=1;
}
return sum;
}
ll ny(ll x)
{
return qc(x,mod-2ll);
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;++i)
{
scanf("%lld",h+i);
g[i][1]=1;
f[i][1]=h[i];
}
int opt=1;
for(int i=2;i<=k;++i)
{
ll sum=0,num=0;
opt^=1;
for(int j=1;j<=n;++j)
{
sum=(sum+f[j][1-opt])%mod;
num=(num+g[j][1-opt])%mod;
f[j][opt]=sum*h[j]%mod;
g[j][opt]=num%mod;
}
}
ll ans1=0,ans2=0;
for(int i=1;i<=n;++i)
ans1=(ans1 + f[i][opt])%mod;
for(int i=1;i<=n;++i)
ans2=(ans2 + g[i][opt])%mod;
printf("%lld",ans1*ny(ans2)%mod);
return 0;
}
posted @   Glowingfire  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程
点击右上角即可分享
微信分享提示