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, int mod) {
    int ans = 1;
    while (k) {
	if (k&1) ans = ans * x % mod;
	x = x * x % mod;
	k >>= 1;
    }
    return ans;
}

int inv(int a, int n) {
    return pow_mod(a, n - 2, n);
}

int t, p, n, A[N][N];
char str[N];

int hash(int c) {
    if (c == ‘*‘) return 0;
    return c - ‘a‘ + 1;
}

void build() {
    for (int i = 0; i < n; i++) {
	A[i][n] = hash(str[i]);
	int tmp = 1;
	for (int j = 0; j < n; j++) {
	    A[i][j] = tmp;
	    tmp = tmp * (i + 1) % p;
	}
    }
}

void gauss() {
    for (int i = 0; i < n; i++) {
	int r;
	for (r = i; r < n; i++)
	    if (A[r][i]) break;
	if (r == n) continue;
	for (int j = i; j <= n; j++) swap(A[r][j], A[i][j]);
	for (int j = 0; j < n; j++) {
	    if (i == j) continue;
	    if (A[j][i]) {
		int tmp = A[j][i] * inv(A[i][i], p) % p;
		for (int k = i; k <= n; k++) {
		    A[j][k] = (((A[j][k] - tmp * A[i][k]) % p) + p) % p;
		}
	    }
	}
    }
    for (int i = 0; i < n; i++)
	printf("%d%c", A[i][n] * inv(A[i][i], p) % p, i == n - 1 ? ‘\n‘ : ‘ ‘);
}

int main() {
    scanf("%d", &t);
    while (t--) {
	scanf("%d%s", &p, str);
	n = strlen(str);
	build();
	gauss();
    }
    return 0;
}
时间: 2024-12-19 02:29:03

UVA 1563 - SETI (高斯消元+逆元)的相关文章

uva 1564 - Widget Factory(高斯消元+逆元)

题目链接:uva 1564 - Widget Factory 题目大意:n种零件,m次工作日程,零件序号从1到n,给出m次工作日程的信息,x,s,e,表示生产了x个零件,从星期s开始到星期e(有可能是多个星期),然后给出生产的x个零件的序号.求每个零件被生产需要多少天(保证在3到10天) 解题思路:因为不能确定每个工作日程具体生产了几天,所以对应列出的方程均为线性模方程(模7),所以在高斯消元的过程中遇到除法要转换成乘上逆元. #include <cstdio> #include <cs

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+....

UVA 11542 - Square(高斯消元)

UVA 11542 - Square 题目链接 题意:给定一些数字,保证这些数字质因子不会超过500,求这些数字中选出几个,乘积为完全平方数,问有几种选法 思路:对每个数字分解成质因子后,发现如果要是完全平方数,选出来的数字的每个质因子个数都必然要是偶数,这样每个质因子可以列出一个异或的方程,如果数字包含质因子,就是有这个未知数,然后进行高斯消元,求出自由变量的个数,每个自由变量可以选或不选,这样的情况就是(2^个数),然后在扣掉什么都不选的1种就是答案了 代码: #include <cstdi

hdu4305Lightning 生成树计数(基尔霍夫矩阵)+高斯消元+逆元

题目:http://acm.hdu.edu.cn/showproblem.php?pid=4305 题意:比较裸的生成树计数问题. 如何处理生成树计数问题? 基尔霍夫矩阵: if i==j  Kir[i][j] = i的度数 if i!=j   Kir[i][j] = i到j的平行边的个数的负数 即,基尔霍夫矩阵 = 度数矩阵 - 邻接矩阵 将基尔霍夫矩阵删去第i行和第i列,余下i-1阶的行列式的值即为生成树个数.(证明略) 求行列式的值可以将行列式转为上三角阵,求对角线上的积即为行列式的值.

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=

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 +

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

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