题意: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 */
时间: 2024-12-19 08:06:10