任务
解法
我们分开考虑每个骰子的贡献;
设
Xi
表示第
i
个骰子的点数。
显然
又
E[Xi]=∑6j=1j∗P[Xi=j]
,
但题目要求我们不能连续两次投相同的骰子;
所以
P[Xi=j]=∑6k=1P[Xi−1=k]∗P[Xi=j|Pi−1=k]
,其中
i>1
P[Xi=j|Pi−1=k]={0,pj+pk∗P[Xi=j|Pi−1=k],j=kj!=k
所以 P[Xi=j|Pi−1=k]=pj1−pk
我们知道
E[Ans1]
后,要求
Ans2=E[(Ans1−E[Ans1])2]
;
也即
Ans2=E[(∑Xi−E[Ans1])2]
由于
E[Ans1]
是常量,我们先让
Xi−E[ans1]n
,则有
Ans2=E[(∑X′i)2]
所以
E[Ans2]=E[(∑X′i)2]=E[∑i=1n∑j=1nXi∗Xj]=E[∑i=1n(Xi)2]+2∗E[∑i=1n∑j=i+1nXi∗Xj]
容易算出 E[∑ni=1(Xi)2] ,
我们考虑 E[∑ni=1∑nj=i+1Xi∗Xj] ;
E[∑i=1n∑j=i+1nXi∗Xj]=∑i=1n∑j=i+1n∑k=16∑l=16k∗l∗P[Xi=k]∗P[Xj=l|Xi=k]=∑k=16∑l=16k∗l∗∑i=1n∑j=i+1nP[Xi=k]∗P[Xj=l|Xi=k]=∑k=16∑l=16k∗l∗∑i=1nP[Xi=k]∗∑j=i+1nP[Xj=l|Xi=k]=∑k=16∑l=16k∗l∗∑i=1nP[Xi=k]∗∑j=1n−i+1P[Xj=l|X1=k]
由于 ∑n−i+1j=1P[Xj=l|X1=k] 只与三元有关,所以可以预处理。
代码
#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<string.h>
#define ll long long
#define db double
using namespace std;
const char* fin="dice.in";
const char* fout="dice.out";
const int inf=0x7fffffff;
const int maxn=100007;
int n,m,i,j,k,l;
db p[7],ans1=0,ans2=0,oo;
db f[maxn][7],g[7][7][maxn],h[7][7][maxn];
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
for (i=1;i<=6;i++) scanf("%lf",&p[i]);
scanf("%d",&n);
for (i=1;i<=n;i++)
for (j=1;j<=6;j++)
if (i==1) f[i][j]=p[j];
else for (k=1;k<=6;k++)
if (j!=k) f[i][j]+=f[i-1][k]*(p[j]/(1-p[k]));
for (i=1;i<=n;i++) for (j=1;j<=6;j++) ans1+=f[i][j]*j;
printf("%lf\n",ans1);
for (i=1;i<=6;i++) for (j=1;j<=6;j++){
if (i!=j){
g[i][j][2]=p[j]/(1-p[i]);
h[i][j][2]=g[i][j][2];
}
}
for (k=3;k<=n;k++){
for (i=1;i<=6;i++) for (j=1;j<=6;j++){
for (l=1;l<=6;l++){
if (j!=l){
g[i][j][k]+=g[i][l][k-1]*(p[j]/(1-p[l]));
}
h[i][j][k]=g[i][j][k]+h[i][j][k-1];
}
}
}
db C=ans1/n;
for (k=1;k<=6;k++)
for (l=1;l<=6;l++)
for (i=1;i<n;i++)
ans2+=(k-ans1/n)*(l-ans1/n)*f[i][k]*h[k][l][n-i+1];
ans2*=2;
for (i=1;i<=n;i++) for (j=1;j<=6;j++) ans2+=(j-ans1/n)*(j-ans1/n)*f[i][j];
printf("%lf\n",ans2);
return 0;
}