poj2065 SETI

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sxy201658506207/article/details/83588341

首先a…z=1..26,*=0 
读入p(模数且为质数),s(下标从0开始),s长度为n 
求方程组 
https://blog.csdn.net/Clove_unique/article/details/54381675

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
const int maxn=100;
int mod,a[maxn][maxn],x[maxn];
bool free_x[maxn];//标记是否是不确定的变元
int var,equ;
char str[maxn];
int p;
void ex_gcd(int a, int b, int &d, int &x, int &y) { if (!b) { x = 1; y = 0; d = a; } else { ex_gcd(b, a%b, d, y, x); y -= x * (a / b); }; }
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
int lcm(int a,int b){return a/gcd(a,b)*b;}//先除后乘防溢出
int inv_exgcd(int a, int m) { int d, x, y;ex_gcd(a, m, d, x, y);return d == 1 ? (x + m) % m : -1; }
void init()
{
    memset(a, 0, sizeof(a));
    var=equ=strlen(str);
    for(int i=0;i<equ;++i)
    {
        int te=1;
        for(int j=0;j<var;++j)
        {
            a[i][j]=te;//做的第一道题关于高斯消元的板子,博主能想到这种构造出k^i的数值也是很服气
            te=te*(i+1)%p;
        }
        a[i][var]=(str[i]=='*')?0:int(str[i]-'a'+1);//常量 题目中说的f(k)
    }
}
int Gauss()
{
    int i,j,k;
    int max_r;// 当前这列绝对值最大的行.
    int col;//当前处理的列
    int ta,tb;
    int LCM;
    int temp;
    for(col=0,k = 0;k < equ && col < var;++k,++col)
    {
        max_r=k;
        for(i=k+1;i<equ;i++)
        {
           if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
        }
        if(max_r!=k)
        {
            for(j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]);
        }
        if(a[k][col]==0)
        {
            k--;continue;
        }
        for(i=k+1;i<equ;i++)
        {// 枚举要删去的行.
            if(a[i][col]!=0)
            {
                LCM = lcm(abs(a[i][col]),abs(a[k][col]));
                ta = LCM/abs(a[i][col]);
                tb = LCM/abs(a[k][col]);
                if(a[i][col]*a[k][col]<0)tb=-tb;//异号的情况是相加
                for(j=col;j<var+1;j++)
                {
                    a[i][j] =((a[i][j]*ta-a[k][j]*tb)%p+p)%p;;
                }
            }
        }
    }
    for (i = k; i < equ; i++)
    {
        if (a[i][col] != 0) return -1;
    }
    for (i = var - 1; i >= 0; i--)//对应的就是从单位矩阵中为1的位置去解,跟着这个循环走两边就知道是怎么接出来唯一解的了
    {
        temp = a[i][var];
        for (j = i + 1; j < var; j++)
        {
            if (a[i][j] != 0) temp =((temp- a[i][j] * x[j])%p+p)%p;//
        }
      int g=inv_exgcd(a[i][i],p);
      x[i]=temp*g%p;
    }
    return 0;
}
int main()
{
    int i, j;
    int t;
    cin>>t;
    while(t--)
    {
    scanf("%d %s",&p,str);
    init();
    Gauss();
    cout<<x[0];
    for (i = 1; i < var; i++)
        printf(" %d",x[i]);
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/sxy201658506207/article/details/83588341