小象涂色 【概率DP】
题目
小象喜欢为箱子涂色。小象现在有c种颜色,编号为0~c-1;还有n个箱子,编号为1~n,最开始每个箱子的颜色为1。小象涂色时喜欢遵循灵感:它将箱子按编号排成一排,每次涂色时,它随机选择$[L,R]$这个区间里的一些箱子(不选看做选0个),为之涂上随机一种颜色。若一个颜色为a的箱子被涂上b色,那么这个箱子的颜色会变成$(a*b)modc$ 。请问在k次涂色后,所有箱子颜色的编号和期望为多少?
分析
用$dp[i][j]$表示一个箱子染了$i$次后变成颜色$j$的概率
那么就有:
$$ dp[i][j]= \begin{cases} dp[i+1][j]*2 \\ (这次保持上一次的颜色j,即为不被染色) \\ + \\ dp[(i*k)mod_c][j]*2*c \\ (这一次不保持j,被染色以及具体被染成了什么) \end{cases} $$
(当然,递推的时候是要逆推的,如下)
$dp[i+1][j]+=dp[i][j]* $$\frac{1}{2}$$ $
$dp[i+1][(j*kk)mod_c]+=dp[i][j]* $$\frac{1}{2}$$ *$$\frac{1}{c}$$ $
下面是参考代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,c,k;
int l,r,T;
int maxx,cnt[51];
double dp[51][101];
int main()
{
cin>>T;
while(T--)
{
memset(dp,0,sizeof(dp));
memset(cnt,0,sizeof(cnt));
cin>>n>>c>>k;
for(int i=1;i<=k;i++)
{
cin>>l>>r;
for(int j=l;j<=r;j++)
{
cnt[j]++;
maxx=max(cnt[j],maxx);
}
}
dp[0][1]=1;
for(int i=0;i<maxx;i++)
for(int j=0;j<c;j++)
{
dp[i+1][j]+=dp[i][j]/2;
for(int kk=0;kk<c;kk++)
dp[i+1][(j*kk)%c]+=dp[i][j]/2/c;
}
double ans=0;
for(int i=1;i<=n;i++)
for(int j=0;j<c;j++)
ans+=dp[cnt[i]][j]*j;
printf("%.9lf\n",ans);
}
return 0;
}

浙公网安备 33010602011771号