题目链接:hdu 5995 Guessing the Dice Roll
题意:
有一个6面的骰子,有n(n≤10)个人每个人猜了一个长度为l(l≤10)的序列,不停的掷骰子直到满足一个人的序列则那个人获胜,求每个人获胜的概率。
题解:
将他们猜的串插入AC自动机,然后转移k次,这里k要足够大才能收敛,然后因为总节点数最多才60个,所以用矩阵来加速。
正解应该是用高斯消元来做这个事情。
1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=(a);i<=(b);++i) 4 using namespace std; 5 6 const int AC_N=100,tyn=6; 7 int s[20],t,n,l,now,all; 8 double ans[20]; 9 const int mat_N=105; 10 11 struct mat{ 12 double c[mat_N][mat_N]; 13 void init(){mst(c,0);} 14 mat operator*(mat b){ 15 mat M;int N=all;M.init(); 16 F(i,0,N)F(j,0,N)if(c[i][j]!=0)F(k,0,N)M.c[i][k]+=c[i][j]*b.c[j][k]; 17 return M; 18 } 19 mat operator^(int k){ 20 mat ans,M=(*this);int N=all;ans.init(); 21 F(i,0,N)ans.c[i][i]=1; 22 while(k){if(k&1)ans=ans*M;k>>=1,M=M*M;} 23 return ans; 24 } 25 }A; 26 27 struct AC_automation{ 28 int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot; 29 inline int getid(int x){return x-1;} 30 void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));} 31 void init(){tot=-1,fail[0]=-1,nw();} 32 void insert(int *s,int len,int idx,int x=0){ 33 for(int i=0,w;i<len;x=tr[x][w],i++) 34 if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot; 35 cnt[x]=idx; 36 } 37 void build(int head=1,int tail=0){ 38 for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i]; 39 while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++) 40 if(tr[x][i]) 41 { 42 fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i]; 43 cnt[tr[x][i]]+=cnt[tr[fail[x]][i]]; 44 } 45 else tr[x][i]=tr[fail[x]][i]; 46 } 47 void solve() 48 { 49 A.init(),all=tot; 50 F(j,0,tot) 51 { 52 if(cnt[j])A.c[j][j]=1; 53 else F(k,0,5)A.c[tr[j][k]][j]+=1.0/6; 54 } 55 A=A^(1<<30); 56 F(i,0,tot)if(cnt[i])ans[cnt[i]]=A.c[i][0]; 57 F(i,1,n)printf("%.6f%c",ans[i]," \n"[i==n]); 58 } 59 60 }AC; 61 62 int main(){ 63 scanf("%d",&t); 64 while(t--) 65 { 66 scanf("%d%d",&n,&l); 67 AC.init(); 68 F(i,1,n) 69 { 70 F(j,0,l-1)scanf("%d",s+j); 71 AC.insert(s,l,i); 72 } 73 AC.build(),AC.solve(); 74 } 75 return 0; 76 }
高斯消元版:
1 #include<bits/stdc++.h> 2 #define mst(a,b) memset(a,b,sizeof(a)) 3 #define F(i,a,b) for(int i=(a);i<=(b);++i) 4 using namespace std; 5 const int AC_N=100,tyn=6; 6 int s[20],t,n,l,now,all; 7 8 #define eps 1e-9 9 const int MAXN=220; 10 double a[MAXN][MAXN],x[MAXN],ans[MAXN]; 11 int equ,var; 12 13 int Gauss() 14 { 15 int i,j,k,col,max_r; 16 for(k=0,col=0;k<equ&&col<var;k++,col++) 17 { 18 max_r=k; 19 for(i=k+1;i<equ;i++) 20 if(fabs(a[i][col])>fabs(a[max_r][col])) 21 max_r=i; 22 if(fabs(a[max_r][col])<eps)return 0; 23 if(k!=max_r) 24 { 25 for(j=col;j<var;j++) 26 swap(a[k][j],a[max_r][j]); 27 swap(x[k],x[max_r]); 28 } 29 x[k]/=a[k][col]; 30 for(j=col+1;j<var;j++)a[k][j]/=a[k][col]; 31 a[k][col]=1; 32 for(i=0;i<equ;i++)if(i!=k) 33 { 34 x[i]-=x[k]*a[i][k]; 35 for(j=col+1;j<var;j++)a[i][j]-=a[k][j]*a[i][col]; 36 a[i][col]=0; 37 } 38 } 39 return 1; 40 } 41 42 struct AC_automation{ 43 int tr[AC_N][tyn],cnt[AC_N],Q[AC_N],fail[AC_N],tot; 44 inline int getid(int x){return x-1;} 45 void nw(){cnt[++tot]=0,fail[tot]=0;memset(tr[tot],0,sizeof(tr[tot]));} 46 void init(){tot=-1,fail[0]=-1,nw();} 47 void insert(int *s,int len,int idx,int x=0){ 48 for(int i=0,w;i<len;x=tr[x][w],i++) 49 if(!tr[x][w=getid(s[i])])nw(),tr[x][w]=tot; 50 cnt[x]=idx; 51 } 52 void build(int head=1,int tail=0){ 53 for(int i=0;i<tyn;i++)if(tr[0][i])Q[++tail]=tr[0][i]; 54 while(head<=tail)for(int x=Q[head++],i=0;i<tyn;i++) 55 if(tr[x][i]) 56 { 57 fail[tr[x][i]]=tr[fail[x]][i],Q[++tail]=tr[x][i]; 58 cnt[tr[x][i]]+=cnt[tr[fail[x]][i]]; 59 } 60 else tr[x][i]=tr[fail[x]][i]; 61 } 62 void solve() 63 { 64 mst(a,0),mst(x,0),equ=var=tot+1; 65 66 F(j,0,tot) 67 { 68 a[j][j]=-1,x[j]=0; 69 if(!cnt[j])F(k,0,5)a[tr[j][k]][j]+=1.0/6; 70 } 71 x[0]=-1; 72 Gauss(); 73 F(i,0,tot)if(cnt[i])ans[cnt[i]]=x[i]; 74 F(i,1,n)printf("%.6f%c",ans[i]," \n"[i==n]); 75 } 76 77 }AC; 78 79 int main(){ 80 scanf("%d",&t); 81 while(t--) 82 { 83 scanf("%d%d",&n,&l); 84 AC.init(); 85 F(i,1,n) 86 { 87 F(j,0,l-1)scanf("%d",s+j); 88 AC.insert(s,l,i); 89 } 90 AC.build(),AC.solve(); 91 } 92 return 0; 93 }
时间: 2024-10-28 20:34:29