码迷,mamicode.com
首页 > 其他好文 > 详细

POJ 2065 SETI 高斯消元解线性同余方程

时间:2017-08-10 22:28:51      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:scan   stdin   algorithm   scanf   while   --   printf   cst   turn   

题意:

给出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 高斯消元解线性同余方程

标签:scan   stdin   algorithm   scanf   while   --   printf   cst   turn   

原文地址:http://www.cnblogs.com/pach/p/7341412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!