其他分享
首页 > 其他分享> > HDU 5955 Guessing the Dice Roll(AC自动机,高斯消元,概率生成函数)

HDU 5955 Guessing the Dice Roll(AC自动机,高斯消元,概率生成函数)

作者:互联网

题目
加强版

你以为我会写AC自动机?对不起这题的加强版只用哈希还只有40行
说实话概率生成函数是个很古老的方法了。
设字符集大小为mmm,字符串下标从1开始。
Fi(x)=j=1P(ji)xjF_i(x) = \sum_{j=1} P(游戏在长度为j的时候玩家i胜利)x^jFi​(x)=∑j=1​P(游戏在长度为j的时候玩家i胜利)xj
G(x)=j=1P(j)xjG(x) = \sum_{j=1} P(游戏在长度为j的时候仍未结束)x^jG(x)=∑j=1​P(游戏在长度为j的时候仍未结束)xj
对于每个串AiA_iAi​,我们在一个未结束的状态后加入它,必定结束,但是结束的时间不同,可能串还没加完就结束了。
所以有:
G(x)(xm)Ai=j=1nk=1min(Ai,Aj)[Ai,1...k=Aj,Ajk+1...Aj]Fj(x)(xm)AikG(x)(\frac x{m})^{|A_i|} = \sum_{j=1}^n \sum_{k=1}^{\min(|A_i|,|A_j|)} [A_{i,1...k} = A_{j,|A_j|-k+1...|A_j|}]F_j(x)(\frac xm)^{|A_i|-k}G(x)(mx​)∣Ai​∣=∑j=1n​∑k=1min(∣Ai​∣,∣Aj​∣)​[Ai,1...k​=Aj,∣Aj​∣−k+1...∣Aj​∣​]Fj​(x)(mx​)∣Ai​∣−k
我们O(n3)O(n^3)O(n3)用哈希算出所有的[Ai,1...k=Aj,Ajk+1...Aj][A_{i,1...k} = A_{j,|A_j|-k+1...|A_j|}][Ai,1...k​=Aj,∣Aj​∣−k+1...∣Aj​∣​]。
那么第iii个玩家胜利的概率为j=0P(ji)=Fi(1)\sum_{j=0} P(游戏在长度为j的时候玩家i胜利) = F_i(1)∑j=0​P(游戏在长度为j的时候玩家i胜利)=Fi​(1)
将上面所有等式用x=1x=1x=1带入可以得到nnn个方程和n+1n+1n+1个变量(包括G(1)G(1)G(1))。
然后加入i=1nFi(1)=1\sum_{i=1}^n F_i(1) = 1∑i=1n​Fi​(1)=1这个等式就可以高斯消元解方程了。

AC Code\mathcal AC \ CodeAC Code

#include<bits/stdc++.h>
#define maxn 305
#define LL long long
#define db double
#define S 131ll
#define eps 1e-13
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;

int n,m;
char s[maxn][maxn];
LL hs[maxn][maxn],pw[maxn];
LL calc(LL *hs,int a,int b){ return hs[b] - hs[a-1] * pw[b-a+1]; }
db a[maxn][maxn],pw2[maxn];

int main(){
	scanf("%d%d",&n,&m);
	pw[0] = pw2[0] = 1;
	rep(i,1,max(n,m)) pw[i] = pw[i-1] * S , pw2[i] = pw2[i-1] * 2;
	rep(i,1,n){
		scanf("%s",s[i]+1);
		rep(j,1,m) hs[i][j] = hs[i][j-1] * S + s[i][j];
	}
	rep(i,1,n) a[0][i] = 1 , a[i][0] = 1;a[0][n+1] = 1;
	rep(i,1,n) rep(j,1,n) rep(k,1,m) if(calc(hs[i],1,k) == calc(hs[j],m-k+1,m))
		a[i][j] -= pw2[k];
	rep(i,0,n){
		rep(j,i+1,n) if(fabs(a[j][i]) > fabs(a[i][i])) swap(a[j],a[i]);
		rep(j,i+1,n){
			db t = a[j][i] / a[i][i];
			rep(k,i,n+1)
				a[j][k] -= a[i][k] * t;
		}
	}
	per(i,n,0){
		rep(j,i+1,n) a[i][n+1] -= a[i][j] * a[j][n+1];
		a[i][n+1] /= a[i][i];
	}
	rep(i,1,n) printf("%.10lf\n",a[i][n+1]);
}

标签:Guessing,AC,...,Ai,hs,rep,Aj,maxn,高斯消
来源: https://blog.csdn.net/qq_35950004/article/details/106443774