bzoj2201 彩色圆环(期望dp)

dp[i][1/0]表示长度为i的序列,第一个和第二个球颜色不同,第一个和最后一个颜色相同/不同 的期望美观程度
定义很绕,没办法呀…毕竟是个环。
p[i]表示i个连续的球颜色相同的概率
枚举最后一段的长度j来O(n)转移,
dp[i][0]=i1j=1p[j]jdp[ij][0](12/m)+p[j]jdp[ij][1](11/m)
dp[i][1]=i1j=1p[j]jdp[ij][0]1/m
因为是个环,所以我们要钦定第一个球,然后枚举第一个球所在段的长度i 来统计答案,贡献就是 iip[i]dp[ni+1] 。如何理解呢?因为是个环,所以覆盖第一个球的长度为i的区间有i个,我们把这个区间缩成一个点,期望长度就是dp[n-i+1]了。特别的,还要加上全是一个颜色的情况,即p[n]*n。

#include 
#include 
#include 
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 210
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m;
double dp[N][2],ans=0,p[N];//p[i]--successive i same color
//dp[i]表示长度为i的序列,第一个和第二个球颜色不同,第一个和最后一个颜色相同(不同)的期望美观程度 
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();p[1]=1;dp[1][1]=1;
    for(int i=2;i<=n;++i) p[i]=p[i-1]*1.0/m;
    for(int i=2;i<=n;++i){
        for(int j=1;j<=i;++j){
            dp[i][0]+=p[j]*j*dp[i-j][0]*(1-2.0/m)+p[j]*j*dp[i-j][1]*(1-1.0/m);
            dp[i][1]+=p[j]*j*dp[i-j][0]*1.0/m;
        }
    }ans+=p[n]*n;
    for(int i=1;i1][0];
    printf("%.5lf\n",ans);
    return 0;
}

你可能感兴趣的:(概率与期望)