【jzoj100004】【Dice】【数学期望】

10 篇文章 0 订阅

题目大意

这里写图片描述

解题思路

Var[X]=E[(XE[X])2]=E[X2+E[X]22XE[X]]=E[X2]E[X]2 设F[i][j]表示第i次出现j的期望和。E[i][j]表示表示第i次出现j的概率和。G[i][j]表示第i次出现j的和的平方的期望。E,F的转移很好推, G[i+1][k]+=(G[i][j]+2F[i][j]k+kkE[i][j])P[k]/(1P[j]);
由于E[X^2]-E[X]^2的精度误差很大,我们考虑 Var[X]=E[(XE[X])2]=E[(XCE[XC])2]=E[(XC(E[X]C))2] 我们发现这种变换是等价的,但是使E[X]^2变为零,这样就减少了精度误差。实践时只需将掷出的数减去E[X]/N即可。

code

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define Min(a,b) ((a<b)?a:b)
#define Max(a,b) ((a>b)?a:b)
#define Fo(i,j,k) for(int i=j;i<=k;i++)
#define Fd(i,j,k) for(int i=j;i>=k;i--)
#define For(i,j) for(int i=Begin[j];i;i=Next[i])
using namespace std;
int const Mxn=1e5+9;
int N;LF P[9],E[Mxn][9],F[Mxn][9],G[Mxn][9];
int main(){
    //freopen("dice.in","r",stdin);
    //freopen("dice.out","w",stdout);
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    Fo(i,1,6)scanf("%lf",&P[i]);
    scanf("%d",&N);
    Fo(i,1,6)E[1][i]=P[i],F[1][i]=i*P[i],G[1][i]=i*i*P[i];
    Fo(i,1,N-1)Fo(j,1,6)Fo(k,1,6)if(j!=k)
        E[i+1][k]+=E[i][j]*P[k]/(1-P[j]),
        F[i+1][k]+=(F[i][j]+k*E[i][j])*P[k]/(1-P[j]);
    LF Ans1=0;
    Fo(i,1,6)Ans1+=F[N][i];
    printf("%.12lf\n",Ans1);Ans1/=N;
    Fo(i,1,N)Fo(j,1,6)F[i][j]=G[i][j]=0;
    Fo(i,1,6)F[1][i]=(i-Ans1)*P[i],G[1][i]=(i-Ans1)*(i-Ans1)*P[i];
    Fo(i,1,N-1)Fo(j,1,6)Fo(k,1,6)if(j!=k)
        F[i+1][k]+=(F[i][j]+(k-Ans1)*E[i][j])*P[k]/(1-P[j]),
        G[i+1][k]+=(G[i][j]+2*F[i][j]*(k-Ans1)+(k-Ans1)*(k-Ans1)*E[i][j])*P[k]/(1-P[j]);
    LF Ans2=0;
    Fo(i,1,6)Ans2+=G[N][i];
    printf("%.12lf",Ans2);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值