ZOJ3329

原来成环可以不用高斯消元,待定系数法也可以

定义 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+3i+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]=aidp[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]+(akdp[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 aidp[0]+bi=(p[0]+akp[k])dp[0]+bkp[k]+1

得到 a i = p [ 0 ] + ∑ a k ∗ p [ k ] a_i=p[0]+\sum a_k*p[k] ai=p[0]+akp[k]

得到 b i = 1 + ∑ b k ∗ p [ k ] b_i=1+\sum b_k*p[k] bi=1+bkp[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]));
	}
}