caioj1270: 概率期望值1:小象涂色
DP深似海,得其得天下。——题记
叕叕叕叕叕叕叕叕叕叕叕(第∞次学DP内容)被D飞了,真的被DP(pa)了。这次D我的是大叫着第二题比较难(小象涂色傻b题)的Mocha(zzz)大佬,表示搞个概率DP,后面还有什么区间、状压、插头DP,不知道这个坑怎么填。唉,心疼。
讲讲这道题吧,在ZZZ大佬的帮助下终于看懂了题,然后他告诉我:
其实全部的箱子都是一样的
然后聪明(???)的我就发现,答案要求的其实就是每个箱子,颜色最后变成0~c-1的期望,再乘以颜色那个数字罢了。
So,弄一个f数组,f[i][j]表示染了i次色,变成j颜色的期望。
然后,上代码。很好理解,我写了注释。
#include<cstdio> #include<iostream> #include<cstring> using namespace std; int cs[110]; double f[110][110];//f[i][j]表示染了i次色,变成j颜色的期望 int main() { int T; scanf("%d",&T); while(T--) { int n,c,K,mmax=0,x,y; scanf("%d%d%d",&n,&c,&K); memset(cs,0,sizeof(cs)); for(int i=1;i<=K;i++) { scanf("%d%d",&x,&y); for(int j=x;j<=y;j++) { cs[j]++; mmax=max(mmax,cs[j]); } } memset(f,0,sizeof(f));f[0][1]=1.0;//一开始全部都是1 for(int i=1;i<=mmax;i++) for(int j=0;j<c;j++) { f[i][j]+=f[i-1][j]/2;//有1/2的概率,不会被涂色 for(int k=0;k<c;k++)f[i][(j*k)%c]+=f[i-1][j]/(2*c);//枚举所有可能被涂的颜色 //被涂的概率是1/2,被涂k颜色概率为1/c,合起来就是1/(2*c) } double ans=0.0; for(int i=1;i<=n;i++)//枚举每一个箱子 for(int j=0;j<c;j++)//被涂成j颜色 ans+=f[cs[i]][j]*j;//i被涂有cs[i]次,由于要求颜色和,乘以颜色 printf("%.9lf\n",ans); } return 0; }
pain and happy in the cruel world.