POJ_2065 SETI 【同余高斯消元】

一、题目

   SETI

二、分析  

  给定一个模数,一串字符串,字符串长度为N,相当于是N个方程的答案,而这N个方程中有N个未知数,要求的就是这N个未知数的值,很显然的高斯消元,遇到模数和除法,用逆元就好。

三、AC代码

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>

using namespace std;
#define ll long long
#define Min(a,b) ((a)>(b)?(b):(a))
#define Max(a,b) ((a)>(b)?(a):(b))
const int maxn = 1e2;
int p;
char s[maxn];
int a[maxn][maxn], x[maxn];
int n, equ, var;

int gcd(int a, int b)
{
    return b == 0 ? a : gcd(b, a%b);
}

int lcm(int a, int b)
{
    return a / gcd(a, b) * b;
}

int inv(int a, int m)
{
    if(a == 1)
        return 1;
    return inv(m%a, m) * (m - m/a)%m;
}

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

int Gauss()
{
    int k, col, max_r;
    for(k = 0, col = 0; k < equ && col < var; k++, col++)
    {
        max_r = k;
        for(int i = k + 1; i < equ; i++)
        {
            if(fabs(a[i][col]) > fabs(a[max_r][col]))
                max_r = i;
        }
        if(a[max_r][col] == 0)
        {
            k--;
            continue;
        }
        if(max_r != k)
        {
            for(int i = col; i < (var + 1); i++)
            {
                swap(a[max_r][i], a[k][i]);
            }
        }
        //消元
        for(int i = k + 1; i < equ; i++)
        {
            if(a[i][col] != 0)
            {
                int LCM = lcm( fabs(a[i][col]), fabs(a[k][col]));
                int ta = LCM / fabs(a[i][col]);
                int tb = LCM / fabs(a[k][col]);
                //异号
                if(a[i][col]*a[k][col] < 0)
                    tb = -tb;
                for(int j = col; j < (var + 1); j++)
                {
                    a[i][j] = ((a[i][j] * ta - a[k][j] * tb) % p + p)%p;
                    a[i][col] = 0;
                }
            }
        }
    }
    for(int i = k; i < equ; i++)
        {
            if(a[i][var+1] != 0)
                return -1;  //无解
        }
        //多解
        if(k < var)
            return var - k;
        for(int i = var - 1; i >= 0; i--)
        {
            int tmp = a[i][var];
            for(int j = i + 1; j < var ;j++)
            {
                if(a[i][j] != 0)
                {
                    tmp -= a[i][j] * x[j];
                }
                tmp = (tmp % p + p) % p;
            }
            x[i] = (tmp * inv(a[i][i], p)) % p;
        }
}

void solve()
{
    equ = n, var = n;
    int res = Gauss();
    for(int i = 0; i < n; i++)
    {
        if(i)
            printf(" ");
        printf("%d", x[i]);
    }
    printf("\n");
}

int main()
{
    int T;
    // freopen("input.txt", "r", stdin);
    // freopen("out.txt", "w", stdout);
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d %s", &p, s);
        n = strlen(s);
        memset(a, 0, sizeof(a));
        for(int i = 0; i < n; i++)
        {
            int res = 1;
            for(int j = 0; j < n; j++)
            {
                a[i][j] = res;
                res = res * (i + 1) % p;
            }
            a[i][n] = getInt(s[i]);
        }
        solve();
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/dybala21/p/11348791.html

时间: 2024-08-05 04:36:51

POJ_2065 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=

[ACM] POJ 2947 Widget Factory (高斯消元)

Widget Factory Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 4436   Accepted: 1502 Description The widget factory produces several different kinds of widgets. Each widget is carefully built by a skilled widgeteer. The time required to

POJ 1166 The Clocks (爆搜 || 高斯消元)

题目链接 题意: 输入提供9个钟表的位置(钟表的位置只能是0点.3点.6点.9点,分别用0.1.2.3)表示.而题目又提供了9的步骤表示可以用来调正钟的位置,例如1 ABDE表示此步可以在第一.二.四.五个钟调正,如原来是0点,那么调正后为3点.问经过那些步骤可以导致9个钟的位置都在0点. 分析: 这个本来是一个高斯消元的题目,但是 听说周期4不是素数, 求解过程中不能进行取余.因为取余可能导致解集变大. 不过也有用高斯消元做的,下面是用高斯消元的分析 ” Discuss也有人讨论了,4不是质数

【弱校胡策】2016.4.14 (bzoj2164)最短路+状压DP+矩阵乘法+高斯消元+树链剖分+线段树+背包DP

cyyz&qhyz&lwyz&gryz弱校胡策 命题人:cyyz ws_fqk T3暴力写挫了 50+10+0滚粗辣! 奇妙的约会(appointment.cpp/c/pas) [问题描述] DQS和sxb在网上结识后成为了非常好的朋友,并且都有着惊人 的OI水平.在NOI2333的比赛中,两人均拿到了金牌,并保送进入 HU/PKU.于是两人决定在这喜大普奔的时刻进行面基. NOI2333参赛选手众多,所以安排了n个考点,DQS在1号考点, 而sxb在n号考点.由于是举办全国性赛事

POJ 2947 Widget Factory (高斯消元 判多解 无解 和解集 模7情况)

题目链接 题意: 公司被吞并,老员工几乎全部被炒鱿鱼.一共有n种不同的工具,编号1-N(代码中是0—N-1), 每种工具的加工时间为3—9天 ,但是现在老员工不在我们不知道每种工具的加工时间,庆幸的是还保留着一些对工人制造工具的记录,对于每个老员工,他的记录包括,他开始工作的时间(在某个星期的星期几),被炒鱿鱼的时间(某个星期的星期几),在第几个星期不知道.....在这段时间里,他正好加工了k件物品,给出了这k件物品的编号.我们要做的就是通过这些记录,来确定每种工具的加工时间是多少. 分析: 对

poj2947--Widget Factory(高斯消元)

题目链接:点击打开链接 题目大意:有n种零件,已知每种零件的加工时间最少为3天最多为9天,现在只知道有m个工程用的时间和加工的零件数,问可不可以求出每种零件的加工时间. 列出对7取余的m个方程,用高斯消元判断是否有解,并解出来. #include <cstdio> #include <cstring> #include <algorithm> using namespace std ; #pragma comment(linker,"/STACK:102400