UVALive - 3490 Generator (AC自动机+高斯消元dp)

初始有一个空串s,从前n个大写字母中不断随机取出一个字母添加到s的结尾,出现模式串t时停止,求停止时s的长度期望。

这道题解法不唯一,比较无脑的方法是对模式串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:\n",++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\n",(G[0][G.n]+mod)%mod);
102     }
103     return 0;
104 }

猜你喜欢

转载自www.cnblogs.com/asdfsag/p/10345306.html
今日推荐