Codeforces 832E Vasya and Shifts - 高斯消元

题目传送门

  快速的传送门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 }
posted @ 2018-03-11 11:48  阿波罗2003  阅读(323)  评论(0编辑  收藏  举报