大江东去,浪淘尽,千古风流人物。故垒西边,人道是,三国周郎赤壁。乱石穿空,惊涛拍岸,卷起千堆雪。江山如画,一时多少豪杰。遥想公瑾当年,小乔初嫁了,雄姿英发。羽扇纶巾,谈笑间,樯橹灰飞烟灭。故国神游,多情应笑我,早生华发。人生如梦,一尊还酹江月。

牛客网 wannafly挑战赛23 C 收益

期望背包DP

复杂度\(O(n*m)\)

前两天模拟考考了这道题

考试时想到了如何设计状态,可惜转移方程写错了。

我的想法:设\(dp[i][j]\)表示前i个人借到j元时的期望支出,\(pp[i][j]\)表示前i个人借到j元的概率,\(ans=\sum_{i=L}^{sum}pp[n][i]*(M-dp[n][i])\)(事实上我考场忘记把M乘上对应的概率了)

但这样做的问题在于,我们必须得计算前i个人借到j元的概率是\(100%\)时的期望支出,转移时会很麻烦(虽然好像也可以做,不过今后考试时应尽可能避免这样的情况),所以不如把借到j元的概率也当做期望的一部分乘上去

最后的方程长这样:

\[pp[i][j]=p[i]×pp[i–1][j–m[i]]+(1–p[i])×pp[i–1][j] \]

\[dp[i][j]=(1–p[i])×dp[i–1][j]+p[i]×(dp[i–1][j–m[i]]+pp[i–1][j–m[i]]×m[i]×r[i]) \]

如何理解第二个dp式子呢?

我们发现\(dp[i][j]\)表示前\(i\)个人借到\(j\)元时的期望支出*\(pp[i][j]\)

\(f[i][j]\)表示前i个人借到j元时的期望支出

也就是说,$$f[i][j]pp[i][j]=(1-p[i])pp[i-1][j]f[i-1][j]+p[i]pp[i-1][j-m[i]](f[i-1][j-m[i]]+m[i]r[i])$$
这样这个看似玄学的式子就可以解释的通了

il int mns(int a,int b){
	return a-b<0?a-b+mod:a-b;
}

il int qpow(int x,int p) {
	int ans=1;
	for(; p; p>>=1) {
		if(p&1) ans=ans*x%mod;
		x=x*x%mod;
	}
	return ans;
}

signed main() {
	//freopen("input.txt","r",stdin);
	read(n),read(L),read(mon);
	int _100=qpow(100,mod-2);
	go(i,1,n)
	read(m[i]),read(r[i]),read(p[i]),sum+=m[i];
	go(i,1,n) {
		r[i]=r[i]*_100%mod;
		p[i]=p[i]*_100%mod;
	}
	pp[0]=1;
	go(i,1,n){
		com(j,sum,m[i]){
			pp[j]=(pp[j]*mns(1,p[i])%mod+pp[j-m[i]]*p[i]%mod)%mod;
			dp[j]=(dp[j]*mns(1,p[i])+(r[i]*m[i]%mod*pp[j-m[i]]%mod+dp[j-m[i]])%mod*p[i])%mod;
		}
		com(j,m[i]-1,0){
			pp[j]=pp[j]*mns(1,p[i])%mod;
			dp[j]=dp[j]*mns(1,p[i])%mod;
		}
	}
	int ans=0;
	go(i,L,sum) ans=(ans+mon*pp[i]%mod-dp[i])%mod;
	cout<<(ans+mod)%mod;
	return 0;
}
posted @ 2019-11-12 15:14  White_star  阅读(103)  评论(0编辑  收藏  举报
}