题意就不说了。
分析:折腾好几天自己写的代码还是看了别人代码后发现几乎没什么复杂度的差别,可是就是一直超时,后来干脆照着别人写啊,一直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 }