hdu 4878 ZCC loves words AC自动机+中国剩余定理+快速幂

题意就不说了。

分析:折腾好几天自己写的代码还是看了别人代码后发现几乎没什么复杂度的差别,可是就是一直超时,后来干脆照着别人写啊,一直WA,就在准备放弃干脆先写这篇博客的时候,又看了一眼WA的代码,发现一个中间变量没有取模直接爆掉了。终于AC了,做了好几天。

思路:对所有单词建立AC自动机,那么每个节点j转移到下一个节点k有方程:dp[i+1][k] =sum{dp[i][j]*Get},表示第i+1步位于k节点,并且由j节点转移过来,其中 Get =  ∏prime[i]*(len[i]+j)。 关键在于这里,结果是要对  179*173*163 取模, 而且Get函数和j有关,也就是走到了第j步,可以先将结果对179, 173, 163取模,然后利用中国剩余定理求出最终结果。

中国剩余定理,可以利用扩展欧几里得求出。我还是不知道我超时的原因,真是给跪了!!!!

别人代码也差不多4000+ms,我写的可能更搓了。

 

代码:

  1 #pragma comment(linker, "/STACK:16777216")
  2 #include <cstdio>
  3 #include <iostream>
  4 #include <cstring>
  5 #include <queue>
  6 #include <vector>
  7 #define inf 0x0f0f0f0f
  8 #define in freopen("data.txt", "r", stdin);
  9 #define  pb push_back
 10 
 11 using namespace std;
 12 typedef long long LL;
 13 
 14 const int maxnode = 44;
 15 const int sigma_size = 26;
 16 int prime[maxnode], vis[1111];
 17 
 18 void getPrime() {
 19     int cnt = 0;
 20     for(int i = 2; i < 1111 && cnt <= 40; i++) {
 21         if(!vis[i]) prime[++cnt] = i;
 22         for(int j = i*i; j < 1111; j += i)
 23             vis[j] = 1;
 24     }
 25 }
 26 
 27 struct Node {
 28     int len, n;
 29     Node(int len, int n): len(len), n(n) {}
 30 };
 31 int ch[maxnode][sigma_size], sz, f[maxnode];
 32 
 33 vector<Node> vec[maxnode];
 34 struct Matrix {
 35     int a[44][44];
 36 } xx[200], E0;;
 37 void maMul(Matrix x, Matrix y, Matrix &res, int mod) {
 38     for(int i = 0; i < sz; i++)
 39         for(int j = 0; j < sz; j++) {
 40             res.a[i][j] = 0;
 41             for(int k = 0; k < sz; k++) {
 42                 res.a[i][j] += x.a[i][k]*y.a[k][j]%mod;
 43                 if(res.a[i][j] >= mod)
 44                     res.a[i][j] -= mod;
 45             }
 46         }
 47 }
 48 struct AC {
 49 
 50     void init() {
 51         sz = 1;
 52         memset(ch[0], 0, sizeof ch[0]);
 53         vec[0].clear();
 54     }
 55     int idx(char ch) {
 56         return ch - 'A';
 57     }
 58     void insert(char *s, int x) {
 59         int u = 0, len = 0;
 60         for(int i = 0; s[i]; i++, len++) {
 61             int c = idx(s[i]);
 62             if(!ch[u][c]) {
 63                 memset(ch[sz], 0, sizeof ch[sz]);
 64                 vec[sz].clear();
 65                 ch[u][c] = sz++;
 66             }
 67             u = ch[u][c];
 68         }
 69         vec[u].pb(Node(len, prime[x]));
 70     }
 71     void getFail() {
 72         queue<int> q;
 73         f[0] = 0;
 74         for(int c = 0; c < sigma_size; c++) {
 75             int u = ch[0][c];
 76             if(u) {
 77                 f[u] = 0;
 78                 q.push(u);
 79             }
 80         }
 81         while(!q.empty()) {
 82             int r = q.front();
 83             q.pop();
 84             for(int c = 0; c < sigma_size; c++) {
 85                 int u = ch[r][c];
 86                 if(!u) {
 87                     ch[r][c] = ch[f[r]][c];
 88                     continue;
 89                 }
 90                 q.push(u);
 91                 int v = f[r];
 92                 while(v && !ch[v][c]) v = f[v];
 93                 f[u] = ch[v][c];
 94             }
 95         }
 96     }
 97     void getMat(int x, int mod) {
 98         for(int i = 0; i < sz; i++) for(int j = 0; j < sz; j++) xx[x].a[i][j] = 0;
 99         for(int u = 0; u < sz; u ++)
100             for(int c = 0; c < sigma_size; c++) {
101                 int v = ch[u][c];
102                 int tv = v;
103                 int res = 1;
104                 while(tv) {
105                     for(int i = 0; i < (int)vec[tv].size(); i++) {
106                         (res *= ((LL)(vec[tv][i].len+x)*vec[tv][i].n%mod))%=mod;
107                     }
108                     tv = f[tv];
109                 }
110                 xx[x].a[v][u] += res;
111                 if(xx[x].a[v][u] >= mod) xx[x].a[v][u] -= mod;
112             }
113     }
114 } solver;
115 
116 int N;
117 LL L;
118 int M[] = {163, 173, 179};
119 int ans[3], a[3];
120 int exgcd(int a, int b, int &x, int &y) {
121     if(!b) {
122         x = 1, y = 0;
123         return a;
124     } else {
125         int tmp = exgcd(b, a%b, y, x);
126         y -= (a/b)*x;
127         return tmp;
128     }
129 }
130 void powmod(Matrix x, LL n, Matrix &res, int mod) {
131     res = E0;
132     while(n) {
133         if(n&1) maMul(res, x, res, mod);
134         maMul(x, x, x, mod);
135         n >>= 1;
136     }
137 }
138 int solve() {
139 
140     solver.getFail();
141     int mul = 1, res = 0;
142 
143     for(int i = 0; i < 3; i++) mul *= M[i];
144     for(int i = 0; i < 3; i++) {
145         a[i] = mul/M[i];
146         Matrix tmp1, tmp2;
147         tmp1 = tmp2 = E0;
148         LL lv = L%M[i];
149         for(int k = M[i]; k >= 1; k--) {
150             solver.getMat(k, M[i]);
151             maMul(tmp1, xx[k], tmp1, M[i]);
152             if(k <= lv)
153                 maMul(tmp2, xx[k], tmp2, M[i]);
154         }
155         powmod(tmp1, L/M[i], tmp1, M[i]);
156         maMul(tmp2, tmp1, tmp1, M[i]);
157         ans[i] = 0;
158         for(int k = 0; k < sz; k++) {
159             ans[i] += tmp1.a[k][0];
160             if(ans[i] >= M[i]) ans[i] -= M[i];
161         }
162         int xx, yy;
163         exgcd(a[i], M[i], xx, yy);
164         res += a[i]*ans[i]%mul*(xx%M[i])%mul;
165         if(res >= mul)
166             res -= mul;
167     }
168     return (res+mul)%mul;
169 }
170 int main() {
171 
172     getPrime();
173     int kase = 0;
174 
175     for(int i = 0; i < 44; i++) for(int j = 0; j < 44; j++) E0.a[i][j] = i == j;
176 
177     while(scanf("%d%I64d", &N, &L) == 2) {
178         solver.init();
179         for(int i = 1; i <= N; i++) {
180             char s[44];
181             scanf("%s", s);
182             solver.insert(s, i);
183         }
184 //        printf("%d\n", sz);
185         printf("Case #%d: %d\n", ++kase, solve());
186     }
187     return 0;
188 }
View Code

 

posted on 2014-09-19 14:23  rootial  阅读(437)  评论(0编辑  收藏  举报

导航