hdu 5995 Guessing the Dice Roll(AC自动机+矩阵)

题目链接:hdu 5995 Guessing the Dice Roll

题意:

有一个6面的骰子,有n(n10)个人每个人猜了一个长度为l(l10)的序列,不停的掷骰子直到满足一个人的序列则那个人获胜,求每个人获胜的概率。

题解:

将他们猜的串插入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]," 
"[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 }
View Code

 高斯消元版:

 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]," 
"[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 }
View Code
原文地址:https://www.cnblogs.com/bin-gege/p/7256011.html