用d[ i ]表示点数和为 i 时还需要掷多少次筛子的期望,pk表示掷一次筛子和为 k 的概率。
d[ i ] = ∑ ( pk * d[ i + k ] ) + p0 * d[ 0 ] + 1;
d[ 0 ]是要求的常数.
令d[ i ] = a[ i ] * d[ 0 ] + b[ i ]
带入递推式中,得到
a[ i ] = p0 + ∑( pk * a[ i + k ] );
b[ i ] = 1 + ∑( pk * b[ i + k ]);
则d[ 0 ] = b[ 0 ] / ( 1 - a[ 0 ] );
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
using namespace std;
int k1, k2, k3, a, b, c, n;
int pk[20];
double p, A[600], B[600];
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d%d%d%d%d%d%d", &n, &k1, &k2, &k3, &a, &b, &c);
memset(pk, 0, sizeof(pk));
p=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!=a || j!=b || k!=c)
pk[i+j+k]++;
memset(A, 0, sizeof(A));
memset(B, 0, sizeof(B));
for(int i=n; i>=0; i--)
{
A[i]=p;
B[i]=1;
for(int j=3; j<=k1+k2+k3; j++)
{
A[i]+=A[i+j]*pk[j]/(k1*k2*k3);
B[i]+=B[i+j]*pk[j]/(k1*k2*k3);
}
}
printf("%.16lf\n", B[0]/(1.0-A[0]));
}
return 0;
}