题意:有三个骰子,分别有k1,k2,k3面,上面的数字1到k1,1到k2,1到k3.每个面出现的概率相同
游戏规则是:
1,有一个计数器,从0开始计数
2.每次摇三个骰子,如果第一个骰子摇到a,第二个骰子摇到b,第三个骰子摇到c,那么计数器归零,否则计数器加上他们三个骰子摇出来的数
3.如果计数器的数字不大于n,那么重复第2步。
问这个游戏结束的期望
分析:
dp[i]:计数器的数字是i,离游戏结束的期望
p[i]:三个骰子数相加是i的概率
p0:计数器归零的概率
dp[i]=∑(dp[i+k]∗p[k])+p0∗dp[0]
但是这个dp[0]是我们要求的啊…
如果成环了可以用高斯
这里可以转化一下系数
设 dp[i]=A[i]*dp[i]+B[i];
带入到上面的式子中就可以得到
A[i]=
∑(p[k]∗A[k+i])+p0
B[i]=
∑(B[i+k]∗p[k])+1
然后递推就行了
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn = 600;
double A[maxn],B[maxn],p[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
mem(A,0);mem(B,0);mem(p,0);
int n,k1,k2,k3,a,b,c;
scanf("%d %d %d %d %d %d %d",&n,&k1,&k2,&k3,&a,&b,&c);
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) continue;
p[i+j+k]++;
}
for(int i=0;i<=k1+k2+k3;i++) p[i]=p[i]/(k1*k2*k3);
p[0]=1.0/(k1*k2*k3);
for(int i=n;i>=0;i--)
{
for(int j=3;j<=(k1+k2+k3);j++)
{ A[i]+=A[i+j]*p[j];B[i]+=B[i+j]*p[j];}
A[i]=A[i]+p[0];B[i]+=1;
}
printf("%.15f\n",B[0]/(1.0-A[0]));
}
return 0;
}