[ACM-ICPC 2018 焦作賽區網路預賽][L.Poor God Water][AC自動機(偽)+矩陣快速冪]
阿新 • • 發佈:2018-12-10
題意
T組資料,構造長度為的串,不含字串的方案數
資料範圍:
分析
AC自動機構造矩陣,但我不會(目前)_(°:з」∠)_
可以將合法的三元串xyz看作xy->yz,這就形成了一個轉移關係那麼11->11就是非法的,13->32也是非法的
這就可以填充一個的矩陣,中元素表示從i轉移到j的合法種數,所有元素和即為答案。
PS:比賽時丟臉的用trie樹手寫了一個的矩陣(把用111->11,21->213這種來表示轉移),線上丟臉ε=ε=ε=ε=ε=ε=┌(; ̄◇ ̄)┘
#pragma GCC optimize(2) #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <set> #include <vector> using namespace std; using LL = long long; const int MOD = 1e9 + 7; struct matrix { LL num[55][55], len; void init(){ memset(num, 0, sizeof(num)); len = 0; } matrix operator *(const matrix &a){ matrix res; res.init(), res.len = a.len; for(int i = 0; i < len; i++) for(int j = 0; j < len; j++) for(int k = 0; k < len; k++) res.num[i][j] += (num[i][k] * a.num[k][j]) % MOD, res.num[i][j] %= MOD; return res; } void getprint(){ for(int i = 0; i < len; i++){ for(int j = 0; j < len; j++) printf("%3lld ", num[i][j]); printf("\n"); } } } A; matrix qpow_matraix(matrix x, LL n); LL T, N; int main(){ A.init(), A.len = 9; int i, j; for(i = 0; i < 9; i++) for(j = 0; j < 3; j++) A.num[i][j + i % 3 * 3] = 1; A.num[0][0] = 0;//11->11 A.num[2][7] = 0;//13->32 A.num[4][4] = 0;//22->22 A.num[5][6] = 0;//23->31 A.num[6][2] = 0;//31->13 A.num[7][5] = 0;//32->23 A.num[8][8] = 0;//33->33 //A.getprint(); cin >> T; while(T--){ cin >> N; if(N == 1){cout << 3 << endl; continue;} else if(N == 2){cout << 9 << endl; continue;} LL ans = 0; matrix tmp = qpow_matraix(A, N - 2); for(i = 0; i < tmp.len; i++) for(j = 0; j < tmp.len; j++) ans += tmp.num[i][j], ans %= MOD; cout << ans << endl; } return 0; } matrix qpow_matraix(matrix X, LL n){ matrix E; E.init(), E.len = X.len; int i; for(i = 0; i <= E.len; i++) E.num[i][i] = 1; while(n){ if(n & 1) E = E * X; X = X * X; n >>= 1; } return E; }