1. 程式人生 > >Codeforces 832E Vasya and Shifts - 高斯消元

Codeforces 832E Vasya and Shifts - 高斯消元

dot lan 線性 har pad sso pow tle ack

題目傳送門

  快速的傳送門I

  快速的傳送門II

題目大意

  (題意比較復雜,請自行閱讀原題)

  可以將原題的字母都看成它們的在字符表中的下標,這樣問題就變成給定$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 }

Codeforces 832E Vasya and Shifts - 高斯消元