【矩阵快速幂】HDU 5318 The Goddess Of The Moon

通道

题意:n个数,A后缀和B的前缀相同,建边,问长度为m的有多少个。

思路:建图,完了

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include <vector>
 4 
 5 using namespace std;
 6 
 7 typedef long long ll;
 8 
 9 const int MAX_N = 57;
10 const ll MOD = 1000000007;
11 
12 typedef vector<ll> vec;
13 typedef vector<vec> mat;
14 mat Mul(mat A, mat B) {
15     mat C(A.size(), vec(B[0].size()));
16     int la = A.size(), lb = B.size(), lc = B[0].size();
17     for (int i = 0; i < la; ++i) 
18         for (int k = 0; k < lb; ++k) 
19             for (int j = 0; j < lc; ++j) 
20                 C[i][j] = (C[i][j] + A[i][k] * B[k][j] % MOD) % MOD;
21     return C;
22 }
23 mat Pow(mat A, ll n) {
24     mat B(A.size(), vec(A.size()));
25     int len = A.size();
26     for (int i = 0; i < len; ++i) B[i][i] = 1;
27     while (n > 0) {
28         if (n & 1) B = Mul(B, A);
29         A = Mul(A, A);
30         n >>= 1;
31     }
32     return B;
33 }
34 
35 int N, M;
36 char str[MAX_N][20];
37 
38 bool check(int i, int j) {
39     if (i == j) return true;
40     int l1 = strlen(str[i]), l2 = strlen(str[j]);
41     for (int k = 2; k <= min(l1, l2); ++k) {
42         int p1 = l1 - k, p2 = 0, found = 1;
43         while (p2 < k) if (str[i][p1++] != str[j][p2++]) found = false;
44         if (found) return true;
45     }
46     return false;
47 }
48 
49 #include <set>
50 #include <string>
51 
52 set<string> mp;
53 
54 int main() {
55     int T;
56     scanf("%d", &T);
57     while (T-- > 0) {
58         scanf("%d%d", &N, &M);
59         mat A(N, vec(N));
60         mp.clear();
61         for (int i = 0; i < N; ++i) {
62             scanf("%s", str[i]);
63             if (strlen(str[i]) < 2) {
64                 --i, --N;
65                 continue;
66             }
67             if (mp.count(str[i])) --i, --N;
68             else mp.insert(str[i]);
69         }
70         if (M <= 1) {
71             printf("%d\n", N);
72             continue;
73         }
74         for (int j = 0; j < N; ++j) {
75             for (int k = 0; k < N; ++k) {
76                 if (check(j, k)) A[j][k] = 1;
77                 else A[j][k] = 0;
78             } 
79         }
80         
81         A = Pow(A, M - 1);
82         ll ans = 0;
83         for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j)
84             ans = (ans + A[i][j]) % MOD;
85         printf("%lld\n", ans);
86     }    
87 
88     return 0;
89 }
90 
91 /*
92 2
93 10 1
94 12 1213 1212 1313231 12312413 12312 4123 1231 3 131
95 */
View Code

 

posted @ 2015-07-28 19:37  mithrilhan  阅读(211)  评论(0编辑  收藏  举报