文章標題 POJ 2065 :SETI (高斯消元)

題目鏈接
題意:給你一個素數P(P<=30000)和一串長爲n的字符串str[]。字母’*’代表0,字母a-z分別代表1-26,這n個字符所代表的數字分別代表f(1)、f(2)….f(n)。
定義f(k) = ∑(0<=i<=n-1)ai*k^i(mod p)
通過定義可以列出n個方程
f(1) = a0 * 1^0 + a1 * 1^1 + a2 * 1^2 ,,,,,,,a(n-1) * 1^n
f(2) = a0 * 1^0 + a1 * 2^1 + a2 * 2^2 ,,,,,,,a(n-1) * 2^n
f(3) = a0 * 3^0 + a1 * 3^1 + a2 * 3^2 ,,,,,,,a(n-1) * 3^n
,,,
,,,
f(n) = a0 * n^0 + a1 * n^1 + a2 * n^2 ,,,,,,,a(n-1) * n^n
然後用高斯消元求解就行了,題目已說明有唯一解
代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;
typedef long long ll;

const int mod=1e9+7;
const int maxn=105;

ll mat[maxn][maxn];
ll p;
char str[105];
ll x[maxn];
bool free_x[maxn] ;

int guass(int n,int m){//n行m列 
    memset (x,0,sizeof (x));//把解集清空,所有變量都標爲自由變量?
    memset (free_x,true,sizeof (free_x));
    int k,col;
    for (k=0,col=0;k<n&&col<m;k++,col++){//枚舉行列
        int max_r=k;//找到該col列元素絕對值最大的那行與第k行交換.(爲了在除法時減小誤差)
        for (int i=k+1;i<n;i++){
            if (fabs(mat[i][col])>fabs(mat[max_r][col]))max_r=i;
        }
        if (max_r!=k){//變換 
            for (int i=k;i<m+1;i++)swap(mat[k][i],mat[max_r][i]);
        }
        for (int i=k+1;i<n;i++)if (mat[i][col]!=0){
            ll x1=mat[i][col],x2=mat[k][col];
            for (int j=col;j<m+1;j++){
                mat[i][j]=mat[i][j]*x2-x1*mat[k][j];
                mat[i][j]=(mat[i][j]%p+p)%p;
            }
        }
    }
    for (int i=k-1;i>=0;i--){
        ll tmp=mat[i][m];
        for (int j=i+1;j<m;j++){
            tmp=((tmp-mat[i][j]*x[j])%p+p)%p;
        }
        while (tmp%mat[i][i])tmp+=p;
        x[i]=((tmp/mat[i][i])%p+p)%p;
    }
    return 0;
}
int n;
int main()
{
    int T;
    scanf ("%d",&T);
    while (T--){
        scanf ("%lld",&p);
        scanf ("%s",str);
        memset (mat,0,sizeof (mat));
        int len=strlen(str); 
        for (int i=0;i<len;i++){
            if (str[i]!='*')mat[i][len]=str[i]-'a'+1;
            mat[i][0]=1;
            for (int j=1;j<len;j++){
                mat[i][j]=(mat[i][j-1]*(i+1))%p;    
            }
        }   
        guass(len,len);
        for(int i=0;i<len;i++){
            if (!i)printf ("%d",x[i]);
            else printf (" %d",x[i]);
        } 
        printf ("\n");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章