POJ2065 SETI(高斯消元 同模方程)

(a1 * 1^0  +   a2 * 1^1  + ...  an * 1^n - 1) % P = f1

....

(a1 * n^0  +   a2 * n^1  + ...  an - 1 * n ^ n - 1) % P = fn

消元中A[k][i] % A[i][i]不为0时将A[k][i]变为他们的最小公倍数,即整行都乘上lcm(A[k][i], A[i][i]) / A[k][i],回代求解时使用逆元

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<queue>
#include<vector>
#include<cmath>
#include<utility>
using namespace std;
typedef long long LL;
const int N = 100, INF = 0x3F3F3F3F;

int hs[256];
int inv[50000];
int p;
LL a[N][N];

template<typename T>
T gcd(T a, T b){
	while(b){
		T t = a % b;
		a = b;
		b = t;
	}
	return a;
}
template<typename T>
T lcm(T a, T b){
	return a / gcd(a, b) * b;
}

template<typename T>
void gauss_jordan(T A[N][N], int n){
    for(int i = 0; i < n; i++){
        //选择一行r与第i行交换
        int r = i;
        for(int j = i; j < n; j++){
            if(A[j][i]){
            	r = j;
            	break;
            }
        }
        if(A[r][i] == 0){
            continue;
        }

        if(r != i){
            for(int j = 0; j <= n; j++){
                swap(A[r][j], A[i][j]);
            }
        }
        for(int k = i + 1; k < n; k++){
            if(A[k][i]){
                if(A[k][i] % A[i][i]){
                    T d = lcm(A[k][i], A[i][i]) / A[k][i];
                    for(int j = i; j <= n; j++){
                        A[k][j] *= d;
                    }
                }
                T d = A[k][i] / A[i][i] % p;
                for(int j = n; j >= i; j--){
                    A[k][j] -=  d * A[i][j] % p;
                    A[k][j] = (A[k][j] % p + p) % p;
                }
            }
        }
    }
    for(int i = n - 1; i >= 0; i--){
    	for(int j = i + 1; j < n; j++){
    		A[i][n] -= A[j][n] * A[i][j] % p;
            A[i][n] = (A[i][n] % p + p) % p;
    	}
    	A[i][n] = A[i][n] * inv[A[i][i] % p] % p;
    }
}

char str[N];
int main(){
    memset(hs, 0, sizeof(hs));
    hs[‘*‘] = 0;
    for(int i = 0; i < 26; i++){
    	hs[i + ‘a‘] = i + 1;
    }
    int t;
    cin>>t;
    while(t--){
    	int n;
    	cin>>p;
    	cin>>str;
    	inv[1] = 1;
    	for(int i = 2; i < p; i++){
    		inv[i] = (p - p / i ) * inv[p % i] % p;
    	}
    	n = strlen(str);
    	memset(a, 0, sizeof(a));
    	for(int i = 0; i < n; i++){
    		a[i][n] = hs[str[i]];
    		a[i][0] = 1;
    		for(int j = 1; j < n; j++){
    			a[i][j] = a[i][j - 1] * (i + 1) % p;
    		}
    	}
    	gauss_jordan(a, n);
    	cout<<a[0][n];
    	for(int i = 1; i < n; i++){
            cout<<‘ ‘<<a[i][n];
    	}
    	cout<<endl;
    }

    return 0;
}

  

时间: 2024-11-21 03:13:57

POJ2065 SETI(高斯消元 同模方程)的相关文章

POJ 2065 SETI (高斯消元 取模)

题目链接 题意: 输入一个素数p和一个字符串s(只包含小写字母和‘*’),字符串中每个字符对应一个数字,'*'对应0,‘a’对应1,‘b’对应2.... 例如str[] = "abc", 那么说明 n=3, 字符串所对应的数列为1, 2, 3. 题目中定义了一个函数: a0*1^0 + a1*1^1+a2*1^2+........+an-1*1^(n-1) = f(1)(mod p), f(1) = str[0] = a = 1; a0*2^0 + a1*2^1+a2*2^2+....

POJ SETI 高斯消元 + 费马小定理

http://poj.org/problem?id=2065 题目是要求 如果str[i] = '*'那就是等于0 求这n条方程在%p下的解. 我看了网上的题解说是高斯消元 + 扩展欧几里德. 然后我自己想了想,就用了高斯消元 + 费马小定理.因为%p是质数,所以很容易就用上了费马小定理,就是在除法的时候用一次就好了.还有就是两个模数相乘还要模一次. #include <cstdio> #include <cstdlib> #include <cstring> #inc

Poj 2065 SETI (高斯消元)

题目连接: http://poj.org/problem?id=2065 题目描述: 给出和明码长度相同的暗码,暗码的每一个字母f(k)都是由明码ai按照 f (k) = ∑0<=i<=n-1a i *ki(mod p) 转化而来 ,已知暗码,求出明码? 解题思路: 使用高斯消元,重要的就是模型转化,列出来增广矩阵题目就距离AC不远了.这个题目的增广矩阵为: a0*1^0 + a1*1^1 + a2*1^2 + ........ + an*1^n = f(1)(mod p); a0*2^0 +

POJ.2065.SETI(高斯消元 模线性方程组)

题目链接 http://blog.csdn.net/Clove_unique/article/details/54381675 http://blog.csdn.net/u013081425/article/details/24299047 http://blog.csdn.net/lin375691011/article/details/38406737 https://www.cnblogs.com/IMGavin/p/5933037.html /* 模意义下的高斯消元,在初等行变换时把k=

UVA 1563 - SETI (高斯消元+逆元)

UVA 1563 - SETI 题目链接 题意:依据题目那个式子.构造一个序列,能生成对应字符串 思路:依据式子能构造出n个方程.一共解n个未知量,利用高斯消元去解,中间过程有取摸过程.所以遇到除法的时候要使用逆元去搞 代码: #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 105; int pow_mod(int x, int k,

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

题意: 给出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> #i

HDU3571 N-dimensional Sphere(高斯消元 同模方程)

每个点到中心距离相等,以第0个点为参考,其他n个点到中心距等于点0到中心距,故可列n个方程 列出等式后二次未知数相消,得到线性方程组 将每个数加上1e17,求答案是再减去,求解时对一个2 * (1e17)以上的一个素数取模. 可用java 中高精度  System.out.println(BigInteger.valueOf(200000000000000001L).nextProbablePrime())  求一个大于2 * (1e17)的质数. #include<cstdio> #incl

【poj2947】高斯消元求解同模方程组【没有AC,存代码】

题意: p start enda1,a2......ap (1<=ai<=n)第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x,加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类,即ai=aj).规定每件装饰物至少生产3 天,最多生产9 天.问每种装饰物需要生产的天数.如果没有解,则输出"Inconsistent data.",如果有多解,则输出"Multiple so

POJ2947Widget Factory(高斯消元解同模方程)

http://poj.org/problem?id=2947 题目大意:有n 种装饰物,m 个已知条件,每个已知条件的描述如下:p start enda1,a2......ap (1<=ai<=n)第一行表示从星期start 到星期end 一共生产了p 件装饰物(工作的天数为end-start+1+7*x,加7*x 是因为它可能生产很多周),第二行表示这p 件装饰物的种类(可能出现相同的种类,即ai=aj).规定每件装饰物至少生产3 天,最多生产9 天.问每种装饰物需要生产的天数.如果没有解,