Codeforces 832E Vasya and Shifts - 高斯消元
可以将原题的字母都看成它们的在字符表中的下标,这样问题就变成给定$n$个$m$维向量$\vec{a_{1}},\vec{a_{2}},\cdots,\vec{a_{n}}$。以及结果向量$\vec{y}$,求有多少组系数$x_{1}, x_{2}, \cdots, x_{n}$满足:
$x_{1}\vec{a_{1}}+x_{2}\vec{a_{2}}+\cdots+x_{n}\vec{a_{n}} = \vec{y}$
这个可以用高斯消元来做。
当存在系数矩阵的零行对应的结果向量的那一位非0,方程组无解。
否则解的个数为$5^{n - r(A)}$。
但是每个询问都去高斯消元会超时。
但每次高斯消元的过程只与系数矩阵有关。因此可以记下高斯消元过程中的线性变换。询问时直接作用于结果向量。
由于我比较懒,所以直接读入所有询问,然后刚开始就处理掉了。
表示很久没打高斯消元,求矩阵的秩写错无数次。
Code
1 /** 2 * Codeforces 3 * Problem#832E 4 * Accepted 5 * Time: 826ms 6 * Memory: 3600k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 12 const int M = 1e9 + 7, max_col = 805; 13 14 int qpow(int a, int pos, int p) { 15 int pa = a, rt = 1; 16 for ( ; pos; pos >>= 1, pa = pa * 1ll * pa % p) 17 if (pos & 1) 18 rt = pa * 1ll * rt % p; 19 return rt; 20 } 21 22 typedef class Matrix { 23 public: 24 int col, row; 25 int a[505][max_col]; 26 boolean zero[505]; 27 28 int guass(int n) { 29 int r = 0; 30 memset(zero, true, sizeof(boolean) * row); 31 for (int i = 0, cur = -1; r < row && i < n; i++, cur = -1) { 32 for (int j = r; j < row && cur == -1; j++) 33 if (a[j][i]) 34 cur = j; 35 if (cur == -1) continue; 36 zero[r] = false; 37 if (cur != i) 38 for (int j = 0; j < col; j++) 39 swap(a[r][j], a[cur][j]); 40 for (int j = 0, x, y; j < row; j++) { 41 if (j == r) continue; 42 x = a[r][i], y = a[j][i]; 43 for (int k = 0; k < col; k++) { 44 a[j][k] = (a[j][k] * x - a[r][k] * y) % 5; 45 if (a[j][k] < 0) 46 a[j][k] += 5; 47 } 48 } 49 r++; 50 } 51 return r; 52 } 53 54 int* operator [] (int p) { 55 return a[p]; 56 } 57 }Matrix; 58 59 int n, m, q; 60 Matrix mat; 61 char buf[505]; 62 63 inline void init() { 64 scanf("%d%d", &n, &m); 65 for (int i = 0; i < n; i++) { 66 scanf("%s", buf); 67 for (int j = 0; j < m; j++) 68 mat[j][i] = (buf[j] - 'a'); 69 } 70 71 scanf("%d", &q); 72 for (int i = 0; i < q; i++) { 73 scanf("%s", buf); 74 for (int j = 0; j < m; j++) 75 mat[j][n + i] = (buf[j] - 'a'); 76 } 77 } 78 79 int ans = 0; 80 boolean hassol[305]; 81 inline void solve() { 82 mat.row = m, mat.col = n + q; 83 int r = mat.guass(n); 84 ans = qpow(5, n - r, M); 85 memset(hassol, true, sizeof(boolean) * q); 86 for (int i = 0; i < m; i++) 87 if (mat.zero[i]) 88 for (int j = 0; j < q; j++) 89 if (mat[i][n + j]) 90 hassol[j] = false; 91 for (int i = 0; i < q; i++) 92 printf("%d\n", (hassol[i]) ? (ans) : (0)); 93 } 94 95 int main() { 96 init(); 97 solve(); 98 return 0; 99 }