原来成环可以不用高斯消元,待定系数法也可以
定义 d p [ i ] dp[i] dp[i]是当前分数为 i i i,到达目标的期望次数
d p [ i ] = 1 + d p [ 0 ] ∗ p [ 0 ] + ∑ k = i + 3 i + k 1 + k 2 + k 3 d p [ k ] ∗ p [ k ] dp[i]=1+dp[0]*p[0]+\sum\limits_{k=i+3}^{i+k1+k2+k3}dp[k]*p[k] dp[i]=1+dp[0]∗p[0]+k=i+3∑i+k1+k2+k3dp[k]∗p[k]
其中 p [ i ] p[i] p[i]为每个分数出现的概率,这个可以预处理出来
发现每个状态都和 d p [ 0 ] dp[0] dp[0]嵌套在一起,无法转移
高斯消元?复杂度上天。
待 定 系 数 法 \color{Red}待定系数法 待定系数法
令 d p [ i ] = a i ∗ d p [ 0 ] + b i dp[i]=a_i*dp[0]+b_i dp[i]=ai∗dp[0]+bi
带入得 d p [ i ] = 1 + d p [ 0 ] ∗ p [ 0 ] + ∑ ( a k ∗ d p [ 0 ] + b k ) ∗ p [ k ] dp[i]=1+dp[0]*p[0]+\sum\limits (a_k*dp[0]+b_k)*p[k] dp[i]=1+dp[0]∗p[0]+∑(ak∗dp[0]+bk)∗p[k]
化简 a i ∗ d p [ 0 ] + b i = ( p [ 0 ] + ∑ a k ∗ p [ k ] ) ∗ d p [ 0 ] + ∑ b k ∗ p [ k ] + 1 a_i*dp[0]+b_i=(p[0]+\sum a_k*p[k])*dp[0]+\sum b_k*p[k]+1 ai∗dp[0]+bi=(p[0]+∑ak∗p[k])∗dp[0]+∑bk∗p[k]+1
得到 a i = p [ 0 ] + ∑ a k ∗ p [ k ] a_i=p[0]+\sum a_k*p[k] ai=p[0]+∑ak∗p[k]
得到 b i = 1 + ∑ b k ∗ p [ k ] b_i=1+\sum b_k*p[k] bi=1+∑bk∗p[k]
一直当 i > n i>n i>n时, a i = b i = 0 a_i=b_i=0 ai=bi=0
所以可以一直向前递推
d p [ 0 ] = p [ 0 ] ∗ d p [ 0 ] + b [ 0 ] dp[0]=p[0]*dp[0]+b[0] dp[0]=p[0]∗dp[0]+b[0]
#include <bits/stdc++.h>
using namespace std;
const int maxn=2009;
double a[maxn],b[maxn],p[maxn];
int n,k1,k2,k3,aa,bb,cc;
int main()
{
int t; cin >> t;
while( t-- )
{
cin >> n >> k1 >> k2 >> k3 >> aa >> bb >> cc;
memset(p,0,sizeof(p));
double p0=1.0/(k1*k2*k3);
for(int i=1;i<=k1;i++)
for(int j=1;j<=k2;j++)
for(int q=1;q<=k3;q++)
if( i!=aa||j!=bb||q!=cc ) p[i+j+q]+=p0;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=n;i>=0;i--)
{
a[i]=p0,b[i]=1.0;
for(int j=3;j<=k1+k2+k3;j++)
{
a[i]+=a[i+j]*p[j];
b[i]+=b[i+j]*p[j];
}
}
printf("%.16lf\n",b[0]/(1-a[0]));
}
}