[ZOJ3329]One Person Game 题解

期望 DP+解系数 Trick

Statement

有三个色子,第 i 个色子有 ki 面,每面面值为 1,2,,ki ,每面出现的概率相同

每次扔出三个色子,将面值加入总得分中。

问期望扔多少次使得总得分大于 n

额外规定: 当 k1=a,k2=b,k3=c 时,总得分清零。

多组数据。

1T300,0n500,1<k1,k2,k36

ZOJ (pintia.cn)

Solution

容易地,设 dp[i] 表示当前得分 i 到目标状态的期望次数

容易 k3 预处理出 p[k] 表示一次扔出得分 k 的概率

那么 dp[i]=(dp[i+k]×p[k])+dp[0]×p[0]

发现每一个式子里面都有 dp[0] 而且答案就是 dp[0]

高消时间炸糊了,这里给出一个 nb 的 Trick:

考虑设 dp[i]=A[i]×dp[0]+B[i]

那么 dp[i]=p[k](A[i+k]×dp[0]+B[i+k])+dp[0]×p[0]+1

所以 dp[i]=((p[k]×A[i+k])+p[0])dp[0]+(p[k]×B[i+k])+1

所以 A[i]=(p[k]×A[i+k])+p[0],B[i]=(p[k]×B[i+k])+1

你发现 A,B 的递推式没有后效性!所以就可以做了

Code

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+5;
const int inf = 2e9;

char buf[1<<23],*p1=buf,*p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
int read(){
    int s=0,w=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')s=s*10+ch-'0',ch=getchar();
    return s*w;
}

double a[1000],b[1000],p[100];
int T,n,k1,k2,k3,x,y,z;

signed main(){
    T=read();
    while(T--){
        memset(a,0,sizeof(a)),memset(b,0,sizeof(b)),memset(p,0,sizeof(p));
        n=read(),k1=read(),k2=read(),k3=read(),x=read(),y=read(),z=read();
        p[0]=1.0/(k1*k2*k3);
        for(int i=1;i<=k1;++i)for(int j=1;j<=k2;++j)
            for(int k=1;k<=k3;++k)if(!(i==x&&j==y&&k==z))
                p[i+j+k]+=p[0];
        for(int i=n;~i;--i){
            a[i]=p[0],b[i]=1;
            for(int k=3;k<=k1+k2+k3;++k)
                a[i]+=p[k]*a[i+k],b[i]+=p[k]*b[i+k];
        }
        printf("%.15lf\n",b[0]/(1.0-a[0]));
    }
    return 0;
}
posted @   _Famiglistimo  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示