任务
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0NXYFhGd192UvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcFDeyIWasdlWzw2RhZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jMzMjNwgTNwIzNwQDM3EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
解法
我们分开考虑每个骰子的贡献;
设 Xi 表示第 i 个骰子的点数。
显然Ans1=∑ni=1E[Xi],
又 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=;
const int maxn=;
int n,m,i,j,k,l;
db p[],ans1=,ans2=,oo;
db f[maxn][],g[][][maxn],h[][][maxn];
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
for (i=;i<=;i++) scanf("%lf",&p[i]);
scanf("%d",&n);
for (i=;i<=n;i++)
for (j=;j<=;j++)
if (i==) f[i][j]=p[j];
else for (k=;k<=;k++)
if (j!=k) f[i][j]+=f[i-][k]*(p[j]/(-p[k]));
for (i=;i<=n;i++) for (j=;j<=;j++) ans1+=f[i][j]*j;
printf("%lf\n",ans1);
for (i=;i<=;i++) for (j=;j<=;j++){
if (i!=j){
g[i][j][]=p[j]/(-p[i]);
h[i][j][]=g[i][j][];
}
}
for (k=;k<=n;k++){
for (i=;i<=;i++) for (j=;j<=;j++){
for (l=;l<=;l++){
if (j!=l){
g[i][j][k]+=g[i][l][k-]*(p[j]/(-p[l]));
}
h[i][j][k]=g[i][j][k]+h[i][j][k-];
}
}
}
db C=ans1/n;
for (k=;k<=;k++)
for (l=;l<=;l++)
for (i=;i<n;i++)
ans2+=(k-ans1/n)*(l-ans1/n)*f[i][k]*h[k][l][n-i+];
ans2*=;
for (i=;i<=n;i++) for (j=;j<=;j++) ans2+=(j-ans1/n)*(j-ans1/n)*f[i][j];
printf("%lf\n",ans2);
return ;
}