POJ 2065 - SETI
http://poj.org/problem?id=2065
概要
数列 \(a_0, \ldots, a_{n-1}\) と素数 \(p\) を用いて,関数 \(f(k)\) を \(f(k) = \sum_{0 \le i \le n-1} a_i k ^ i\) と定める. \(f(k)\) は \(1 \le k \le n\) に対して \(0 \le f(k) \le 26\) を満たすとする.
\(p\) と \(f(1), \ldots, f(n)\) の値が与えられるので,\(a_0, \ldots, a_{n-1}\) を答える.
制約
- \(\mbox{max}(n, 26) \lt p \le 30000\)
- \(0 \le a_i \lt p\)
解法
\(a_{i}\) に関する連立方程式を \(\mbox{GF}(p)\) の上で解くだけ.
poj/2065.cc1 #include <iostream> 2 #include <vector> 3 using namespace std; 4 5 struct mod/*{{{*/ 6 { 7 int m; 8 vector<int> tbl; 9 mod(int a) : m(a), tbl(m+1) 10 { 11 for (int x = 1; x < m; x++) { 12 tbl[x] = pow(x, a-2); 13 } 14 } 15 int pow(int x, int e) 16 { 17 if (e == 0) { 18 return 1; 19 } else if (e & 1) { 20 return (x * pow(x, e-1))%m; 21 } else { 22 const int y = pow(x, e>>1); 23 return (y*y)%m; 24 } 25 } 26 int operator()(int x) const { return ((x%m)+m)%m; } 27 int inv(int x) const { return tbl[x]; } 28 };/*}}}*/ 29 30 vector<int> gaussian_elimination(vector<vector<int> > a, vector<int> b, const mod& M)/*{{{*/ 31 { 32 const int N = a.size(); 33 34 for (int i = 0; i < N; i++) { 35 for (int j = i+1; a[i][i] == 0 && j < N; j++) { 36 swap(a[i], a[j]); 37 swap(b[i], b[j]); 38 } 39 if (a[i][i] == 0) { 40 continue; 41 } 42 43 const int t = M.inv(a[i][i]); 44 for (int k = i; k < N; k++) { 45 a[i][k] = M(a[i][k] * t); 46 } 47 b[i] = M(b[i] * t); 48 49 for (int j = 0; j < N; j++) { 50 if (i == j) { 51 continue; 52 } 53 const int u = a[j][i]; 54 for (int k = i; k < N; k++) { 55 a[j][k] = M(a[j][k] - u*a[i][k]); 56 } 57 b[j] = M(b[j] - u*b[i]); 58 } 59 } 60 61 for (int i = 0; i < N; i++) { 62 if (a[i][i] == 0 && b[i] != 0) { 63 // no solution 64 return vector<int>(); 65 } 66 } 67 return b; 68 }/*}}}*/ 69 70 int main() 71 { 72 ios::sync_with_stdio(false); 73 int T; 74 cin >> T; 75 while (T-- > 0) { 76 int p; 77 cin >> p; 78 string s; 79 cin >> s; 80 const int N = s.size(); 81 mod m(p); 82 vector<vector<int> > mat(N, vector<int>(N)); 83 vector<int> b(N); 84 for (int i = 0; i < N; i++) { 85 for (int j = 0; j < N; j++) { 86 mat[i][j] = m.pow(i+1, j); 87 } 88 if (s[i] == '*') { 89 b[i] = 0; 90 } else { 91 b[i] = s[i]-'a'+1; 92 } 93 } 94 95 const vector<int> x = gaussian_elimination(mat, b, m); 96 for (vector<int>::const_iterator it = x.begin(); it != x.end(); ++it) { 97 if (it != x.begin()) { 98 cout << " "; 99 } 100 cout << *it; 101 } 102 cout << endl; 103 } 104 return 0; 105 }