POJ 2065 高斯消元+线性模方程

来源:互联网 发布:新论语 严介和 淘宝网 编辑:程序博客网 时间:2024/06/09 19:35

消元过程为保持整数用最小公倍数。

回代过程用线性模方程

计算过程注意保持模n下的非负数。

#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <map>#include <set>#include <algorithm>#include <ctime>#include <vector>#include <string>using namespace std;int p,n;char s[1000];int a[100][100];int ans[100];int gcd(int a,int b){    return b==0 ? a : gcd(b,a%b);}int lcm(int a,int b){    return a/gcd(a,b)*b;}int extend_gcd(int a,int b,int &x,int &y){    if(b==0)    {        x=1;y=0;        return a;    }    int res=extend_gcd(b,a%b,y,x);    y=y-a/b*x;    return res;}void gauss(){    for(int i=0;i<n;++i)    {        int pivot=i;        for(int k=i+1;k<n;++k)            if(abs(a[k][i])>abs(a[pivot][i]))                pivot=k;        if(a[i][i]==0)            continue;        if(pivot!=i)        {            for(int j=0;j<=n;++j)                swap(a[pivot][j],a[i][j]);        }        // elimination        for(int k=i+1;k<n;++k)            if(a[k][i])        {            int mul=lcm(a[i][i],a[k][i]);            int ma=mul/a[i][i];            int mb=mul/a[k][i];            for(int j=0;j<=n;++j)                a[k][j]=((a[k][j]*mb%p-a[i][j]*ma%p)%p+p)%p;        }    }    for(int i=n-1;i>=0;--i)    {        for(int k=i+1;k<n;++k)        {            a[i][n]-=a[i][k]*ans[k]%p;            a[i][n]=(a[i][n]%p+p)%p;        }        int x,y;        extend_gcd(a[i][i],p,x,y);        ans[i]=(x*a[i][n]%p+p)%p;    }}int main (){    int T;scanf("%d",&T);    while(T--)    {        scanf("%d%s",&p,s);        memset(a,0,sizeof(a));        n=strlen(s);        for(int i=1;i<=n;++i)            for(int t=1,j=0;j<n;++j,t*=i,t%=p)                a[i-1][j]=t;        for(int i=0;i<n;++i)            if(s[i]=='*')                a[i][n]=0;            else a[i][n]=s[i]-'a'+1;        gauss();        for(int i=0;i<n;++i)        {            printf("%d",ans[i]);            if(i<n-1)                printf(" ");            else puts("");        }    }    return 0;}


原创粉丝点击