POJ 2065 SETI 高斯消元解线性同余方程
Posted Pacify
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 2065 SETI 高斯消元解线性同余方程相关的知识,希望对你有一定的参考价值。
题意:
给出mod的大小,以及一个不大于70长度的字符串。每个字符代表一个数字,且为矩阵的增广列。系数矩阵如下
1^0 * a0 + 1^1 * a1 + ... + 1^(n-1) * an-1 = f(1)
2^0 * a0 + 2^1 * a1 + ... + 2^(n-1) * an-1 = f(2)
........
n^0 * a0 + n^1 * a1 + ... + n^(n-1) * an-1 = f(n)
快速幂取模下系数矩阵
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = 100; int a[MAXN][MAXN], x[MAXN]; int MOD; void debug(int n, int m) { for(int i=0; i<n; i++) { for(int j=0; j<m; j++) printf("%d ", a[i][j]); printf(" %d\n", a[i][m]); } puts("**************************************************************"); } int powermod(int a,int b) { int ans=1; a%=MOD; while(b) { if(b&1) ans=ans*a%MOD; a=a*a%MOD; b=b>>1; } return ans; } int gcd(int a,int b) //递归算法 { return b ? gcd(b, a%b) : a; } int lcm(int a, int b) { return a*b/gcd(a,b); } int Guass(int equ,int var) { // debug(equ, var); int row,col; row=col=0; while(row<equ && col<var) { //列非零主 int r=row; for(int i=row; i<equ; i++) if(a[i][col]!=0) { r=i; break; } if(r!=row) { for(int j=col; j<var+1; j++) swap(a[row][j],a[r][j]); } if(a[row][col]==0)//说明有自由变元 { col++; continue; } //消元 for(int i=row+1; i<equ; i++) { if(a[i][col]==0) continue; int l = lcm(a[row][col],a[i][col]); int ta = l/a[row][col]; int tb = l/a[i][col]; for(int j=col; j<var+1; j++) a[i][j] = ((tb*a[i][j] - ta*a[row][j]) % MOD + MOD) %MOD; } // debug(equ, var); row++; col++; } // for(int i=row; i<equ; i++) // if(a[i][var]!=0) return -1; // if(row < var) return 1; for(int i=row-1; i>=0; i--) { int tmp = a[i][var]; for(int j=i+1; j<var; j++) tmp = ((tmp - x[j]*a[i][j])%MOD + MOD)%MOD; while(tmp%a[i][i]) tmp += MOD; x[i] = tmp/a[i][i]%MOD; } return 0; } char s[100]; int main() { // freopen("in.txt", "r", stdin); int t; scanf("%d", &t); while(t--) { scanf("%d%s", &MOD, s); int n = strlen(s); memset(a, 0, sizeof(a)); for(int i=0; i<n; i++) for(int j=0; j<n; j++) a[i][j] = powermod(i+1,j); for(int i=0; i<n; i++) a[i][n] = s[i]==‘*‘? 0:s[i]-‘a‘+1; Guass(n, n); for(int i=0; i<n; i++) { if(x[i]<0) x[i] += MOD; printf("%d%c", x[i], i==n-1? ‘\n‘:‘ ‘); } } return 0; }
以上是关于POJ 2065 SETI 高斯消元解线性同余方程的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2947-Widget Factory(高斯消元解同余方程式)