我们设 \(f[i][j]\)表示目前前 \(i\) 个宝箱的期望贡献的 \(j\) 次方。
根据题意可得 $f[i][k]=(f[i-1][1]+a[i])^k \cdot p[i]+(f[i-1][1]+b[i])^k \cdot (1-p[i]) $
这个式子很难处理,不妨用二项式定理优化
优化后式子则为:\(f[i][k]= \sum _{j=0}^{k} C_{k}^{j} \cdot f[i-1][j] \cdot a[i]^{k-j} \cdot p[i]+ \sum _{j=0}^{k}f[i-1][j] \cdot b[i]^{k-j} \cdot (1-p[i])\)
合并一下
\(f[i][k]= \sum _{j=0}^{k} C_{k}^{j} \cdot f[i-1][j] \cdot (a[i]^{k-j} \cdot p[i] +b[i]^{k-j} \cdot (1-p[i]) )\)
到这里我们就可以在 \(O(nk)\) 预处理\((a[i]^{k-j} \cdot p[i] +b[i]^{k-j} \cdot (1-p[i]) )\),再 \(O(nk^2)\) 转移了。
using namespace std;
#define int long long
const int N=1e4+107;
const int mod=998244353;
int n,k;
int p[N],a[N],b[N];
int read()
{
int f=1,s=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return f*s;
}
int qpow(int a,int b)
{
int ans=1;
while(b)
{
if(b&1) ans=ans*a%mod;
b=b>>1;
a=a*a%mod;
}
return ans;
}
int ans=0;
int fac[200],inv[N];
void init()
{
fac[0]=inv[0]=1;
for(int i=1;i<120;i++)
{
fac[i]=fac[i-1]*i%mod;
inv[i]=qpow(fac[i],mod-2);
}
}
int C(int n,int m){return fac[n]*inv[n-m]%mod*inv[m]%mod;}
int f[N][120],tmp[N][120];
signed main()
{
init();
n=read(),k=read();
for(int i=1;i<=n;i++)
{
p[i]=read(),a[i]=read(),b[i]=read();
}
int sum=0;
for(int i=1;i<=n;i++)
{
tmp[i][0]=f[i][0]=1;
for(int j=1;j<=k;j++)
{
tmp[i][j]=(qpow(a[i],j)*p[i]%mod+qpow(b[i],j)*(1-p[i]+mod)%mod)%mod;
}
}
for(int i=1;i<=k;i++)
{
f[1][i]=tmp[1][i];
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<=k;j++)
{
for(int g=0;g<=j;g++)
{
f[i][j]=(f[i][j]+f[i-1][g]*C(j,g)%mod*tmp[i][j-g]%mod)%mod;
}
}
}
printf("%lld",f[n][k]);
return 0;
}`
标签:箱子,ch,cdot,sum,int,ans,inv
From: https://www.cnblogs.com/zhengchenxi/p/18374464