POJ2065 SETI(高斯消元 同模方程)
(a1 * 1^0 + a2 * 1^1 + ... an * 1^n - 1) % P = f1
....
(a1 * n^0 + a2 * n^1 + ... an - 1 * n ^ n - 1) % P = fn
消元中A[k][i] % A[i][i]不为0时将A[k][i]变为他们的最小公倍数,即整行都乘上lcm(A[k][i], A[i][i]) / A[k][i](不过后来看题解发现有更巧妙的方法不用求lcm),回代求解时使用逆元
#include<cstdio> #include<iostream> #include<cstdlib> #include<cstring> #include<string> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<utility> using namespace std; typedef long long LL; const int N = 100, INF = 0x3F3F3F3F; int hs[256]; int inv[50000]; int p; LL a[N][N]; template<typename T> T gcd(T a, T b){ while(b){ T t = a % b; a = b; b = t; } return a; } template<typename T> T lcm(T a, T b){ return a / gcd(a, b) * b; } template<typename T> void gauss_jordan(T A[N][N], int n){ for(int i = 0; i < n; i++){ //选择一行r与第i行交换 int r = i; for(int j = i; j < n; j++){ if(A[j][i]){ r = j; break; } } if(A[r][i] == 0){ continue; } if(r != i){ for(int j = 0; j <= n; j++){ swap(A[r][j], A[i][j]); } } for(int k = i + 1; k < n; k++){ if(A[k][i]){ if(A[k][i] % A[i][i]){ T d = lcm(A[k][i], A[i][i]) / A[k][i]; for(int j = i; j <= n; j++){ A[k][j] *= d; } } T d = A[k][i] / A[i][i] % p; for(int j = n; j >= i; j--){ A[k][j] -= d * A[i][j] % p; A[k][j] = (A[k][j] % p + p) % p; } } } } for(int i = n - 1; i >= 0; i--){ for(int j = i + 1; j < n; j++){ A[i][n] -= A[j][n] * A[i][j] % p; A[i][n] = (A[i][n] % p + p) % p; } A[i][n] = A[i][n] * inv[A[i][i] % p] % p; } } char str[N]; int main(){ memset(hs, 0, sizeof(hs)); hs['*'] = 0; for(int i = 0; i < 26; i++){ hs[i + 'a'] = i + 1; } int t; cin>>t; while(t--){ int n; cin>>p; cin>>str; inv[1] = 1; for(int i = 2; i < p; i++){ inv[i] = (p - p / i ) * inv[p % i] % p; } n = strlen(str); memset(a, 0, sizeof(a)); for(int i = 0; i < n; i++){ a[i][n] = hs[str[i]]; a[i][0] = 1; for(int j = 1; j < n; j++){ a[i][j] = a[i][j - 1] * (i + 1) % p; } } gauss_jordan(a, n); cout<<a[0][n]; for(int i = 1; i < n; i++){ cout<<' '<<a[i][n]; } cout<<endl; } return 0; }