[Gauss]POJ2065 SETI

题意: *代表0,a-z代表1-26

题目第三行给了一个公式 f (k) = ∑0<=i<=n-1aiki (mod p)  {f(i)是输入的一串字符串中第i的字母代表的数  ai即xi是要求的  p是输入给的}

然后列出len个方程 用Gauss求解就好了

这题保证有唯一解 因此不必考虑无解或自由未知量

  1 int mod;
  2 LL quick(LL a, LL b)
  3 {
  4     LL ans=1;
  5     while(b)
  6     {
  7         if(b & 1)ans=(ans*a)%mod;
  8         a=(a*a)%mod;
  9         b>>=1;
 10     }
 11     return ans%mod;
 12 }
 13 int gcd(int a, int b)
 14 {
 15     return b==0? a:gcd(b, a%b);
 16 }
 17 int lcm(int a, int b)
 18 {
 19     return a/gcd(a, b)*b;
 20 }
 21 void ex_gcd(int a, int b, int &x, int &y)
 22 {
 23     if(b)
 24     {
 25         ex_gcd(b, a%b, x, y);
 26         int tmp=x;
 27         x=y;
 28         y=tmp-(a/b)*y;
 29     }
 30     else
 31     {
 32         x=1, y=0;
 33         return ;
 34     }
 35 }
 36
 37 int a[300][300];  // 增广矩阵
 38 int x[300];  // 解
 39 int free_x[300]; // 标记是否为自由未知量
 40
 41 void Gauss(int n, int m) // n个方程 m个未知数 即 n行m+1列
 42 {
 43     //转换为阶梯形式
 44     int col=0, k, num=0;
 45     for(k=0; k<n && col<m; k++, col++)
 46     {
 47         //枚举行
 48         int max_r=k;
 49         for(int i=k+1; i<n; i++) //找到第col列元素绝对值最大的那行与第k行交换
 50             if(abs(a[i][col])>abs(a[max_r][col]))
 51                 max_r=i;
 52         if(max_r!=k)// 与第k行交换
 53             for(int j=col; j<m+1; j++)
 54                 swap(a[k][j], a[max_r][j]);
 55         if(!a[k][col])// 说明该col列第k行以下全是0了
 56         {
 57             k--;
 58             free_x[num++]=col;
 59             continue;
 60         }
 61         for(int i=k+1; i<n; i++) // 枚举要删除的行
 62             if(a[i][col])
 63             {
 64                 int LCM=lcm(abs(a[i][col]), abs(a[k][col]));
 65                 int ta=LCM/abs(a[i][col]);
 66                 int tb=LCM/abs(a[k][col]);
 67                 if(a[i][col]*a[k][col]<0)
 68                     tb=-tb;
 69                 for(int j=col; j<m+1; j++)
 70                     a[i][j]=((a[i][j]*ta-a[k][j]*tb)%mod+mod)%mod;
 71             }
 72     }
 73
 74     for(int i=k; i<n; i++)
 75         if(a[i][col])
 76             return ; // 无解
 77
 78     if(k<m)   //m-k为自由未知量个数
 79         return ;
 80
 81     //  唯一解 回代
 82     for(int i=m-1; i>=0; i--)
 83     {
 84         int tmp=a[i][m];
 85         for(int j=i+1; j<m; j++)
 86         {
 87             if(a[i][j])
 88                 tmp-=a[i][j]*x[j];
 89             tmp=(tmp%mod+mod)%mod;
 90         }
 91         int xx, yy;
 92         ex_gcd(a[i][i], mod, xx, yy);
 93         xx=(xx%mod+mod)%mod;
 94         x[i]=(tmp*xx)%mod;
 95     }
 96     return ;
 97 }
 98
 99 void init()
100 {
101     memset(a, 0, sizeof(a));
102     memset(x, 0, sizeof(x));
103 }
104
105 char s[105];
106 int main()
107 {
108     int T;
109     while(~scanf("%d", &T))
110         while(T--)
111         {
112             init();
113             scanf("%d%s", &mod, s);
114             int n=strlen(s);
115             for(int i=0; i<n; i++)
116             {
117                 a[i][n]=(s[i]==‘*‘? 0:s[i]-‘a‘+1);
118                 for(int j=0; j<n; j++)
119                     a[i][j]=quick(i+1, j);
120             }
121             Gauss(n, n);
122             for(int i=0; i<n; i++)
123             {
124                 printf("%d", x[i]);
125                 if(i==n-1)
126                     printf("\n");
127                 else
128                     printf(" ");
129             }
130         }
131     return 0;
132 }

POJ 2065

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

[Gauss]POJ2065 SETI的相关文章

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

【poj2065】 SETI

http://poj.org/problem?id=2065 (题目链接) 题意 题意半天看不懂..给你一个素数P(P<=30000)和一串长为n的字符串str[].字母'*'代表0,字母a-z分别代表1-26,这n个字符所代表的数字分别代表f(1).f(2)....f(n).定义: ${f(k)=\sum_{i=0}^{n-1}{a_ik^i~(mod~p)}~(1<=k<=n,0<=a_i<P)}$,求a0.a1.....an-1.题目保证肯定有唯一解. Solution

高斯消元法(Gauss Elimination)【超详解&amp;模板】

高斯消元法,是线性代数中的一个算法,可用来求解线性方程组,并可以求出矩阵的秩,以及求出可逆方阵的逆矩阵.高斯消元法的原理是:若用初等行变换将增广矩阵 化为 ,则AX = B与CX = D是同解方程组. 所以我们可以用初等行变换把增广矩阵转换为行阶梯阵,然后回代求出方程的解. 1.线性方程组 1)构造增广矩阵,即系数矩阵A增加上常数向量b(A|b) 2)通过以交换行.某行乘以非负常数和两行相加这三种初等变化将原系统转化为更简单的三角形式(triangular form) 注:这里的初等变化可以通过

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 (高斯消元 取模)

题目链接 题意: 输入一个素数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 2065 SETI(高斯消元解模方程组)

题目: SETI Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 1693   Accepted: 1054 Description For some years, quite a lot of work has been put into listening to electromagnetic radio signals received from space, in order to understand what

POJ_2065 SETI 【同余高斯消元】

一.题目  SETI 二.分析 给定一个模数,一串字符串,字符串长度为N,相当于是N个方程的答案,而这N个方程中有N个未知数,要求的就是这N个未知数的值,很显然的高斯消元,遇到模数和除法,用逆元就好. 三.AC代码 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <cmath>

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和)

HDU 1588 Gauss Fibonacci(矩阵高速幂+二分等比序列求和) ACM 题目地址:HDU 1588 Gauss Fibonacci 题意: g(i)=k*i+b;i为变量. 给出k,b,n,M,问( f(g(0)) + f(g(1)) + ... + f(g(n)) ) % M的值. 分析: 把斐波那契的矩阵带进去,会发现这个是个等比序列. 推倒: S(g(i)) = F(b) + F(b+k) + F(b+2k) + .... + F(b+nk) // 设 A = {1,1,

hdu 5755(GAuss 消元)

Gambler Bo Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1152    Accepted Submission(s): 471Special Judge Problem Description Gambler Bo is very proficient in a matrix game. You have a N×M m