Poj 2065 SETI (高斯消元)

题目连接:

  http://poj.org/problem?id=2065

题目描述:

  给出和明码长度相同的暗码,暗码的每一个字母f(k)都是由明码ai按照 f (k) = ∑0<=i<=n-1i *ki(mod p) 转化而来 ,已知暗码,求出明码?

解题思路:

  使用高斯消元,重要的就是模型转化,列出来增广矩阵题目就距离AC不远了。这个题目的增广矩阵为:

  a0*1^0 + a1*1^1 + a2*1^2 + ........ + an*1^n = f(1)(mod p);

  a0*2^0 + a1*2^1 + a2*2^2 + ........ + an*2^n = f(2)(mod p);

  a0*3^0 + a1*3^1 + a2*3^2 + ........ + an*3^n = f(3)(mod p);

           ...

           ...

           ...

  a0*(n-2)^0 + a1*(n-2)^1 + a2*(n-2)^2 + ........ + an*(n-2)^n = f(n-2)(mod p);

  a0*(n-1)^0 + a1*(n-1)^1 + a2*(n-2)^2 + ........ + an*(n-1)^n = f(n-1)(mod p);

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 using namespace std;
 6 const int maxn = 75;
 7 typedef __int64 LL;
 8 LL det[maxn][maxn], x[maxn];
 9 int  var, equ, p;
10 void gauss ()
11 {
12     int k, col;
13     for (k=col=0; k<equ&&col<var; k++,col++)
14     {
15         int min_i = k;
16         for (int i=k+1; i<equ; i++)//减小误差的出现
17             if (det[min_i][col] < det[i][col])
18                 min_i = i;
19         if (min_i != k)
20             for (int i=col; i<=var; i++)
21                 swap (det[k][i], det[min_i][i]);
22         if (det[k][col] == 0)
23         {
24             k --;
25             continue;
26         }
27         for (int i=k+1; i<equ; i++)
28             if (det[i][col])
29             {
30                 int x, y;//防止精度出现误差
31                 x = det[k][col];
32                 y = det[i][col];
33                 for (int j=col; j<=var; j++)
34                     det[i][j] = (((det[i][j]*x - det[k][j]*y) % p) + p) % p;
35             }
36     }
37     for (int i=k-1; i>=0; i--)
38     {
39         LL temp = det[i][var];
40         for (int j=i+1; j<var; j++)
41             temp = ((temp - det[i][j]*x[j]) % p + p) % p;
42         while (temp%det[i][i])
43             temp += p;//保证结果的精度
44         x[i] = ((temp / det[i][i])%p + p) % p;
45     }
46 }
47 int main ()
48 {
49     int t;
50     scanf ("%d", &t);
51     while (t --)
52     {
53         char str[maxn];
54         scanf ("%d %s", &p, str);
55         var = equ = strlen(str);
56         for (int i=0; i<equ; i++)
57         {
58             LL num = 1;
59             for (int j=0; j<equ; j++)
60             {
61                 det[i][j] = num;
62                 num = (num * (i + 1)) % p;
63             }
64             if (str[i] == '*')
65                 det[i][var] = 0;
66             else
67                 det[i][var] = str[i] - 'a' + 1;
68         }
69         gauss ();
70         for (int i=0; i<var-1; i++)
71             printf ("%I64d ", x[i]);
72         printf ("%I64d\n", x[var-1]);
73     }
74     return 0;
75 }

 

posted @ 2015-07-07 23:36  罗茜  阅读(173)  评论(0编辑  收藏  举报