金箱子

我们设 \(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;
}`
posted @ 2024-08-22 19:04  zhengchenxi  阅读(25)  评论(0)    收藏  举报