UVALive - 3490 Generator (AC自动机+高斯消元dp)
Posted asdfsag
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVALive - 3490 Generator (AC自动机+高斯消元dp)相关的知识,希望对你有一定的参考价值。
初始有一个空串s,从前n个大写字母中不断随机取出一个字母添加到s的结尾,出现模式串t时停止,求停止时s的长度期望。
其实这道题不用AC自动机和高斯消元也能过,但像我这种菜鸡怎么舍得花时间去推一个自己不熟悉的方法
比较无脑的方法是对模式串t建一个单串AC自动机,设u为自动机上的一个结点,dp[u]为从该结点出发走到终结状态时的期望步数,则dp[u]=∑(1+dp[v])/n,v为u的后继状态。特别地,终结状态的dp值为0。
这样一来,就可以列出线性方程组进行高斯消元了。由于答案非常大,用double会损失精度,所以改成longlong。
由于有除法的存在,为了防止出现除不开的现象,我写了个大模数+逆元的版本,还需要用到按位乘。(闲的蛋疼系列)
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 5 const ll mod=(1ll<<61)-1; 6 int m,ka; 7 char s[15]; 8 ll Mul(ll x,ll p) { 9 if(p<0)p+=mod; 10 ll ret=0; 11 for(; p; x=(x+x)%mod,p>>=1)if(p&1)ret=(ret+x)%mod; 12 return ret; 13 } 14 ll Pow(ll x,ll p) { 15 ll ret=1; 16 for(; p; x=Mul(x,x)%mod,p>>=1)if(p&1)ret=Mul(ret,x)%mod; 17 return ret; 18 } 19 ll inv(ll x) {return Pow(x,mod-2);} 20 21 struct Mat { 22 static const int N=15; 23 int n; 24 ll a[N][N]; 25 ll* operator[](int x) {return a[x];} 26 void gauss() { 27 for(int i=0; i<n; ++i) { 28 int r=i; 29 if(!a[r][i]) { 30 for(int k=i+1; k<n; ++k)if(a[k][i]) {r=k; break;} 31 } 32 if(r!=i)for(int j=i; j<=n; ++j)swap(a[i][j],a[r][j]); 33 for(int k=i+1; k<n; ++k) { 34 ll tmp=Mul(a[k][i],inv(a[i][i])); 35 for(int j=i; j<=n; ++j)a[k][j]=(a[k][j]-Mul(a[i][j],tmp))%mod; 36 } 37 } 38 for(int i=n-1; i>=0; --i) { 39 for(int j=i+1; j<n; ++j)a[i][n]=(a[i][n]-Mul(a[j][n],a[i][j]))%mod; 40 a[i][n]=Mul(a[i][n],inv(a[i][i])); 41 } 42 } 43 } G; 44 45 struct AC { 46 static const int N=100+10,M=26; 47 int go[N][M],pre[N],tot,end[N]; 48 int idx(char ch) {return ch-‘A‘;} 49 void init() {tot=0; newnode();} 50 int newnode() { 51 int u=tot++; 52 memset(go[u],0,sizeof go[u]); 53 end[u]=pre[u]=0; 54 return u; 55 } 56 void ins(char* s) { 57 int u=0,n=strlen(s); 58 for(int i=0; i<n; u=go[u][idx(s[i])],++i) 59 if(!go[u][idx(s[i])])go[u][idx(s[i])]=newnode(); 60 end[u]=1; 61 } 62 void build() { 63 queue<int> q; 64 for(int i=0; i<M; ++i)if(go[0][i])q.push(go[0][i]); 65 while(!q.empty()) { 66 int u=q.front(); 67 q.pop(); 68 for(int i=0; i<M; ++i) { 69 if(go[u][i]) { 70 pre[go[u][i]]=go[pre[u]][i]; 71 q.push(go[u][i]); 72 } else go[u][i]=go[pre[u]][i]; 73 } 74 } 75 } 76 void gettransmat(Mat& G) { 77 G.n=tot; 78 int n=tot; 79 for(int i=0; i<n; ++i) 80 for(int j=0; j<=n; ++j) 81 G[i][j]=j==i?1:0; 82 for(int i=0; i<tot; ++i)if(!end[i]) { 83 for(int j=0; j<m; ++j)G[i][go[i][j]]=(G[i][go[i][j]]-inv(m))%mod; 84 G[i][n]=(G[i][n]+1)%mod; 85 } 86 } 87 } ac; 88 89 int main() { 90 int T; 91 scanf("%d",&T); 92 while(T--) { 93 if(ka)puts(""); 94 printf("Case %d: ",++ka); 95 ac.init(); 96 scanf("%d%s",&m,s); 97 ac.ins(s); 98 ac.build(); 99 ac.gettransmat(G); 100 G.gauss(); 101 printf("%lld ",(G[0][G.n]+mod)%mod); 102 } 103 return 0; 104 }
以上是关于UVALive - 3490 Generator (AC自动机+高斯消元dp)的主要内容,如果未能解决你的问题,请参考以下文章
UVALive-8138 Number Generator 概率dp+优化
刚刚!第七次人口普查出炉!男性比女性多3490万,老龄化进一步加深
[2016-03-05][UVALive][4104][MODEX]