POJ_2065
题目既然没有说无解的情况就当做一定有解来看待了,根据题意可以列出n个同余方程,然后用高斯消元+拓展欧几里得求得每个ai就可以了。
#include<stdio.h> #include<string.h> #include<iostream> #define MAXD 80 using namespace std; int mat[MAXD][MAXD], N, P, ans[MAXD]; char b[MAXD], ch[128]; void prepare() { int i; for(i = 'a'; i <= 'z'; i ++) ch[i] = i - 'a' + 1; ch['*'] = 0; } void exgcd(int a, int b, int &x, int &y) { if(b == 0) x = 1, y = 0; else exgcd(b, a % b, y, x), y -= x * (a / b); } int powmod(int a, int n) { int ans = 1, t = a; while(n) { if(n & 1) ans = (ans * t) % P; n >>= 1; t = (t * t) % P; } return ans; } void init() { int i, j, k; scanf("%d", &P); scanf("%s", b); N = strlen(b); for(i = 0; i < N; i ++) { mat[i][N] = ch[b[i]]; for(j = 0; j < N; j ++) mat[i][j] = powmod(i + 1, j); } } void gauss() { int i, j, k, a, b, x, y; for(i = 0; i < N; i ++) { if(mat[i][i] == 0) { for(j = i + 1; j < N; j ++) if(mat[j][i]) { for(k = i; k <= N; k ++) swap(mat[i][k], mat[j][k]); break; } } a = mat[i][i]; for(j = i + 1; j < N; j ++) if(mat[j][i]) { b = mat[j][i]; for(k = i; k <= N; k ++) mat[j][k] = (mat[j][k] * a - mat[i][k] * b) % P; } } for(i = N - 1; i >= 0; i --) { a = (mat[i][i] + P) % P, b = mat[i][N]; for(j = i + 1; j < N; j ++) b = (b - mat[i][j] * ans[j]) % P; b = (b + P) % P; exgcd(a, P, x, y); ans[i] = (((x % P) * b) % P + P) % P; } } void solve() { int i; gauss(); printf("%d", ans[0]); for(i = 1; i < N; i ++) printf(" %d", ans[i]); printf("\n"); } int main() { int t; prepare(); scanf("%d", &t); while(t --) { init(); solve(); } return 0; }