当前位置:编程学习 > C/C++ >>

Poj 2605 SETI (数学_高斯消元)

题目大意:给定一个素数p和一个字符串串str。令f[i] = Num(str[i]),Num(str[i])表示当str[i]为*的时候为0,str[i]为a-z的时候为str[i]-a+1.
          接着得到n(str[i]的长度)个方程组,每个方程组格式为(a1*k^0+a2*k^1+...+an*k^(n-1)) mod p = f[k] mod p (1<=k<=n),ai为未知量,让我们解这个方程组,输出n个解。

解题思路:比较裸的高斯消元,我抄一抄模板就过掉了,但是让我讲高斯消元的核心思想还是不会讲,线代老师死得早啊。
     讲下我认识的高斯消元类题目一般步骤吧:1、利用题目信息建立方程组 2、将方程组化为增广矩阵 3、将增广矩阵化为行阶梯矩阵 4、求解。第1步是关键也是难点,后面的可以套用模版。具体的分析见这篇文章: 
测试数据:
3
29 hello*earth
out: 8 13 9 13 4 27 18 10 12 24 15

C艹代码:
[cpp] 
#include <iostream> 
#include <string> 
#include <string.h> 
#include <cmath> 
#include <stdio.h> 
#include <algorithm> 
using namespace std; 
#define MAX 71 
 
 
char str[MAX]; 
int  n,m,p,x[MAX]; 
int  mat[MAX][MAX]; 
 
 
void Initial() { 
            
    int i,j,k = 1; 
    memset(x,0,sizeof(x)); 
    for (i = 0; i < n; ++i) { 
         
        mat[i][m] = str[i]=='*'?0:str[i]-'a'+1; 
 
        for (k = 1,j = 0; j < m; ++j) 
            mat[i][j] = k,k = k * (i + 1) % p; 
        //for (j = 0; j < m; ++j) 
        //    printf("%d%c",mat[i][j],j==m-1?'\n':' '); 
    } 

inline int gcd(int x,int y) { 
     
    int r = x % y; 
    while (r) { 
         
        x = y,y = r; 
        r = x % y; 
    } 
    return y; 

inline int lcm(int x,int y) { 
 
    return x/gcd(x,y) * y; 

void Gauss() { 
 
    int i,j,row,max_r,col; 
    int ta,tb,temp,LCM; 
    int free_x_num,free_index; 
 
 
    col = row = 0; 
    for (; row < n && col < m; ++row,++col) { 
 
        max_r = row; 
        for (i = row + 1; i < n; ++i) 
            if (abs(mat[i][col]) > abs(mat[max_r][col])) 
                max_r = i; 
 
 
        if (max_r != row) 
            for (j = row; j <= m; ++j) 
                swap(mat[row][j],mat[max_r][j]); 
        if (mat[row][col] == 0) { 
 
            row--; 
            continue; 
        } 
 
 
        for (i = row + 1; i < n; ++i) 
            if (mat[i][col] != 0) { 
 
                LCM = lcm(abs(mat[i][col]),abs(mat[row][col])); 
                ta = LCM / abs(mat[i][col]); 
                tb = LCM / abs(mat[row][col]); 
                if (mat[i][col] * mat[row][col] < 0) 
                    tb = -tb; 
                for (j = col; j <= m; ++j) 
                    mat[i][j] = (mat[i][j] * ta - mat[row][j] * tb) % p; 
            } 
    } 
    //printf("yes,you can ac\n"); 
 
 
    for (i = m - 1; i >= 0; --i) { 
 
        temp = mat[i][m]; 
        for (j = i + 1; j < m; ++j) 
            if (mat[i][j] != 0) 
                temp = ((temp - mat[i][j] * x[j])%p + p) % p; 
        while (temp % mat[i][i]) temp = temp + p; 
        x[i] = (temp / mat[i][i] + p) % p; 
    } 

 
 
int main() www.zzzyk.com

    int i,j,k,t; 
     
 
    scanf("%d",&t); 
    while (t--) { 
         
        scanf("%d %s",&p,str); 
        n = strlen(str); 
        m = n,Initial(); 
 
 
        Gauss(); 
        for (i = 0; i < m; ++i) 
            printf("%d%c",x[i],i==m-1?'\n':' '); 
    } 

 作者:woshi250hua

补充:软件开发 , C++ ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,