题目描述
题解
令f(i)表示得分为i时到结束的期望
显然这道题>0的点都可以从0转移过来,0也可以从每一个>0的点转移过来
所以这题就应该画柿子了
f(i)=∑f(i+k)p(k)+f(0)P+1
,其中p(i)表示掷出和为i的骰子的概率,P表示掷出a,b,c的概率
每一项都包含f(0),令f(i)=pa(i)f(0)+pb(i),那么f(i+k)=pa(i+k)f(0)+pb(i+k)
将其代入
f(i)=∑(pa(i+k)f(0)+pb(i+k))p(k)+f(0)P+1
f(i)=(∑pa(i+k)p(k)+P)f(0)+∑pb(i+k)p(k)+1
得到
pa(i)=∑pa(i+k)p(k)+P
,
pb(i)=∑pb(i+k)p(k)+1
然后就可以dp出pa和pb了
最终
f(0)=pb(0)1−pa(0)
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int T,n,k1,k2,k3,a,b,c;
double P,ans,p[50],pa[1005],pb[1005];
void clear()
{
n=k1=k2=k3=a=b=c=0;
P=ans=0;
memset(p,0,sizeof(p));memset(pa,0,sizeof(pa));memset(pb,0,sizeof(pb));
}
int main()
{
scanf("%d",&T);
while (T--)
{
clear();
scanf("%d%d%d%d%d%d%d",&n,&k1,&k2,&k3,&a,&b,&c);
P=1.0/((double)k1*(double)k2*(double)k3);
for (int i=1;i<=k1;++i)
for (int j=1;j<=k2;++j)
for (int k=1;k<=k3;++k)
if (i!=a||j!=b||k!=c) p[i+j+k]+=P;
for (int i=n;i>=0;--i)
{
for (int j=3;j<=k1+k2+k3&&(i+j)<=n;++j)
pa[i]+=pa[i+j]*p[j],pb[i]+=pb[i+j]*p[j];
pa[i]+=P,pb[i]+=1.0;
}
ans=pb[0]/(1-pa[0]);
printf("%.15lf\n",ans);
}
}