• Codeforces 1172C1. Nauuo and Pictures (easy version)(期望DP)


    Codeforces 1172C1. Nauuo and Pictures (easy version)(期望DP)

    题目链接:C1. Nauuo and Pictures (easy version)

    题意:

    一个网站共有 n n n张图片,每张图片有权值 w i wi wi,每次访问时看到第 i i i张的概率为 w i ∑ j = 1 n w j \frac{wi}{\sum_{j=1}^n wj } j=1nwjwi,其中 a i ai ai 1 1 1表示 N a u u o Nauuo Nauuo喜欢这张图片,为 0 0 0表示不喜欢, N a u u o Nauuo Nauuo会访问 m m m次网站,每次如果看到的是喜欢的图片就令其权值 + 1 +1 +1,是不喜欢的就令其权值 − 1 -1 1,问访问 m m m次后各图片权值的期望为多少

    题解:

    我们可以发现对每个 i i i单独枚举其情况时,其他图片的权值我只需要知道喜欢和不喜欢权值的总和就行,不需要知道具体那一个的权值,这样我们就能把所以权值分成三类:
    一类是我当前 i i i的权值,一类是总的其他图片中我喜欢的权值和,一类是总的其他图片中我不喜欢的权值和。

    首先我们预处理出所有初始权重 w i wi wi的总和 s u m sum sum,所有我喜欢的图片的初始权重的总和 x x x,和所有我不喜欢的图片的初始权重的总和 y y y
    我们用 d p [ i ] [ j ] [ k ] [ q ] dp[i][j][k][q] dp[i][j][k][q]表示对于第 i i i张图片,当前一共访问了 j j j次, k k k次访问的是我喜欢的图片, q q q次是当前图片的概率,那么我们将图片 i i i a [ i ] a[i] a[i] 1 1 1和为 0 0 0分成两类:

    a [ i ] a[i] a[i] 1 1 1:
    1.当前遇到我喜欢的但不是第 i i i张图片:
    d p [ i ] [ j ] [ k ] [ q ] + = d p [ i ] [ j − 1 ] [ k − 1 ] [ q ] ∗ x + k − 1 − ( w [ i ] + q ) s u m − ( j − k ) + k − 1 dp[i][j][k][q]+=dp[i][j-1][k-1][q]*\frac{x+k-1-(w[i]+q)}{sum-(j-k)+k-1} dp[i][j][k][q]+=dp[i][j1][k1][q]sum(jk)+k1x+k1(w[i]+q), k ≥ 1 k\geq1 k1
    因为转移的状态 d p [ i ] [ j − 1 ] [ k − 1 ] [ q ] dp[i][j-1][k-1][q] dp[i][j1][k1][q]中遇到喜欢的有 k − 1 k-1 k1次,所以遇到不喜欢的有 j − 1 − ( k − 1 ) j-1-(k-1) j1(k1)次,所以经过这 j j j次后,当前总权值为 s u m − ( j − k ) + k − 1 sum-(j-k)+k-1 sum(jk)+k1,其中喜欢的权值增加了(k-1),不喜欢的减少了 j − 1 − ( k − 1 ) j-1-(k-1) j1(k1),因为当前遇到了 q q q次图片 i i i,所以图片 i i i权值变为 w i + q wi+q wi+q,因此喜欢的部分除去当前图片 i i i的概率为 x + k − 1 − ( w [ i ] + q ) s u m − ( j − k ) + k − 1 \frac{x+k-1-(w[i]+q)}{sum-(j-k)+k-1} sum(jk)+k1x+k1(w[i]+q),(剩下的情都况按照这个模式转移就可以了)
    2.遇到我喜欢的且当前是第 i i i张图片
    3.遇到我不喜欢的(因为 a [ i ] a[i] a[i] 1 1 1,当前不可能是第 i i i张)

    a [ i ] a[i] a[i] 0 0 0:
    (这里需要注意因为 a [ i ] a[i] a[i] 0 0 0,所以 w i wi wi的权值应当是减)
    1.遇到我喜欢的( a [ i ] a[i] a[i] 0 0 0,当前不可能是第 i i i个)
    2.遇到我不喜欢的但不是第 i i i
    3.遇到我不喜欢的且是第 i i i

    主要思路就是上面这样了,具体细节和实现可以参考代码和注释:

    ll dp[52][52][52][52];//对于第i个,当前一共访问了j次,k次是我喜欢的,q次是当前点的概率
    int a[52];
    int w[52];
    ll inv[3100];
    ll mi(ll a,ll b){
    	ll res=1;
    	while(b){
    		if(b%2){
    			res=res*a%mod;
    		}
    		a=a*a%mod;
    		b/=2;
    	}
    	return res;
    }
    void init(){
    	inv[0]=1;
    	for(int i=1;i<=3000;i++){
    		inv[i]=mi(i,mod-2);
    	}
    }
    ll ans[52];//对应期望
    int main(){
    /*cout<
    /*cout<
    	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);//同步流
    	int n,m;
    	init();//求出inv逆元
    	cin>>n>>m;
    	ll sum=0;//总初始权值
    	ll x=0,y=0;//总喜欢的初始权值,总不喜欢的初始权值
    	for(int i=1;i<=n;i++){
    		cin>>a[i];
    	}
    	for(int i=1;i<=n;i++){
    		cin>>w[i];
    		if(a[i]){
    			x+=w[i];
    		}
    		else{
    			y+=w[i];
    		}
    		sum+=w[i];
    	}
    	for(int i=1;i<=n;i++){
    		dp[i][0][0][0]=1;
    		for(int j=1;j<=m;j++){
    			for(int k=0;k<=j;k++){
    				for(int q=0;q<=j;q++){
    					if(a[i]){
    						//遇到我喜欢的但不是第i个
    						if(k>=1){
    							(dp[i][j][k][q]+=(dp[i][j-1][k-1][q]*(x+k-1-(w[i]+q))%mod)*inv[sum-(j-k)+k-1]%mod)%=mod;
    						}
    						//遇到我喜欢的且是第i个
    						if(k>=1&&q>=1){
    							(dp[i][j][k][q]+=(dp[i][j-1][k-1][q-1]*(w[i]+q-1)%mod)*inv[sum-(j-k)+k-1]%mod)%=mod;
    						}
    						//遇到我不喜欢的(a[i]为1,当前不可能是第i个)
    						(dp[i][j][k][q]+=(dp[i][j-1][k][q]*(y-(j-1-k))%mod)*inv[sum-(j-1-k)+k]%mod)%=mod;
    					}
    					else{
    						if(q>j-k){
    							continue;
    						}
    						//遇到我喜欢的(a[i]为0,当前不可能是第i个)
    						if(k>=1){
    							(dp[i][j][k][q]+=(dp[i][j-1][k-1][q]*(x+k-1)%mod)*inv[sum-(j-k)+k-1]%mod)%=mod;
    						}
    						//遇到我不喜欢的但不是第i个
    						(dp[i][j][k][q]+=(dp[i][j-1][k][q]*(y-(j-1-k)-(w[i]-q))%mod)*inv[sum-(j-1-k)+k]%mod)%=mod;
    						//遇到我不喜欢的且是第i个
    						if(q>=1){
    							(dp[i][j][k][q]+=(dp[i][j-1][k][q-1]*(w[i]-(q-1))%mod)*inv[sum-(j-1-k)+k]%mod)%=mod;
    						}
    					}
    					if(j==m){//计算每个w的最终期望
    						ll val=w[i];//w[i]的最终权值
    						if(a[i]){
    							val+=q;
    						}
    						else{
    							val-=q;
    						}
    						if(val>=0){//小于0的情况是不合法的
    							ans[i]=(ans[i]+dp[i][j][k][q]*val%mod)%mod;//对应期望,期望=权值*概率
    						}
    					}
    				}
    			}
    		}
    		cout<<ans[i]<<endl;
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
  • 相关阅读:
    7-94 求N分之一序列前N项和
    机器学习(18)——分类算法(补充)
    Python 关于函数的使用
    三维扫描体数据的VTK体绘制程序设计
    苍穹外卖-day05
    2023最全的性能测试种类介绍,这6个种类特别重要!
    Canvas字体高度计算与PDF高度如何统一
    目标检测算法 - YOLOv1
    风火编程--playwright爬虫
    高效管理和盘点固定资产的办法
  • 原文地址:https://blog.csdn.net/m0_56280274/article/details/126064508