• POJ2065 SETI 高斯消元


      题目连接:http://poj.org/problem?id=2065

      高斯消元求出上三角矩阵后,求出 a×x = b(mod p),即 a×x - p×y=b,用扩展欧几里得求出x。

      1 //STATUS:C++_AC_32MS_156KB
      2 #include <functional>
      3 #include <algorithm>
      4 #include <iostream>
      5 //#include <ext/rope>
      6 #include <fstream>
      7 #include <sstream>
      8 #include <iomanip>
      9 #include <numeric>
     10 #include <cstring>
     11 #include <cassert>
     12 #include <cstdio>
     13 #include <string>
     14 #include <vector>
     15 #include <bitset>
     16 #include <queue>
     17 #include <stack>
     18 #include <cmath>
     19 #include <ctime>
     20 #include <list>
     21 #include <set>
     22 #include <map>
     23 using namespace std;
     24 //using namespace __gnu_cxx;
     25 //define
     26 #define pii pair<int,int>
     27 #define mem(a,b) memset(a,b,sizeof(a))
     28 #define lson l,mid,rt<<1
     29 #define rson mid+1,r,rt<<1|1
     30 #define PI acos(-1.0)
     31 //typedef
     32 typedef long long LL;
     33 typedef unsigned long long ULL;
     34 //const
     35 const int N=73;
     36 const int INF=0x3f3f3f3f;
     37 const int MOD=100000,STA=8000010;
     38 const LL LNF=1LL<<60;
     39 const double EPS=1e-8;
     40 const double OO=1e15;
     41 const int dx[4]={-1,0,1,0};
     42 const int dy[4]={0,1,0,-1};
     43 const int day[13]={0,31,28,31,30,31,30,31,31,30,31,30,31};
     44 //Daily Use ...
     45 inline int sign(double x){return (x>EPS)-(x<-EPS);}
     46 template<class T> T gcd(T a,T b){return b?gcd(b,a%b):a;}
     47 template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
     48 template<class T> inline T lcm(T a,T b,T d){return a/d*b;}
     49 template<class T> inline T Min(T a,T b){return a<b?a:b;}
     50 template<class T> inline T Max(T a,T b){return a>b?a:b;}
     51 template<class T> inline T Min(T a,T b,T c){return min(min(a, b),c);}
     52 template<class T> inline T Max(T a,T b,T c){return max(max(a, b),c);}
     53 template<class T> inline T Min(T a,T b,T c,T d){return min(min(a, b),min(c,d));}
     54 template<class T> inline T Max(T a,T b,T c,T d){return max(max(a, b),max(c,d));}
     55 //End
     56 
     57 int A[N][N];//增广矩阵
     58 int B[N];//解集
     59 bool free_x[N];//标记是否是不确定的变元
     60 int T,n,m,k,p;
     61 
     62 //
     63 void Debug(int equ,int var)
     64 {
     65     int i, j;
     66     for(i=0;i<equ;i++){
     67         for(j=0;j<=var;j++)
     68             printf("%4d",A[i][j]);
     69         putchar('\n');
     70     }
     71     putchar('\n');
     72 }
     73 //
     74 
     75 void extgcd(int a,int b,int &d,int &x,int &y)
     76 {
     77     if(!b){d=a;x=1;y=0;}
     78     else {extgcd(b,a%b,d,y,x);y-=x*(a/b);}
     79 }
     80 
     81 inline int gcd(int a,int b)
     82 {
     83     int t;
     84     while(b!=0)
     85     {
     86         t=b;
     87         b=a%b;
     88         a=t;
     89     }
     90     return a;
     91 }
     92 
     93 inline int lcm(int a,int b)
     94 {
     95     return a/gcd(a,b)*b;//先除后乘防溢出
     96 }
     97 
     98 // 高斯消元法解方程组(Gauss-Jordan elimination).(-2表示有浮点数解,但无整数解,
     99 //-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
    100 //有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
    101 int Gauss(int equ,int var)
    102 {
    103     int i,j,k;
    104     int max_r; // 当前这列绝对值最大的行.
    105     int col; //当前处理的列
    106     int ta,tb;
    107     int LCM;
    108     int temp;
    109     int free_x_num;
    110     int free_index;
    111 
    112     for(int i=0;i<=var;i++)
    113     {
    114         B[i]=0;
    115         free_x[i]=true;
    116     }
    117     //转换为阶梯阵.
    118     col=0; // 当前处理的列
    119     for(k = 0;k < equ && col < var;k++,col++)
    120     {// 枚举当前处理的行.
    121 // 找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减小误差)
    122         max_r=k;
    123         for(i=k+1;i<equ;i++)
    124         {
    125             if(abs(A[i][col])>abs(A[max_r][col])) max_r=i;
    126         }
    127         if(max_r!=k)
    128         {// 与第k行交换.
    129             for(j=k;j<var+1;j++) swap(A[k][j],A[max_r][j]);
    130         }
    131         if(A[k][col]==0)
    132         {// 说明该col列第k行以下全是0了,则处理当前行的下一列.
    133             k--;
    134             continue;
    135         }
    136         for(i=k+1;i<equ;i++)    //  i=0高斯约当消元,才能在多解的情况下判断变元是否确定
    137         {// 枚举要删去的行.
    138             if(A[i][col]!=0 && i!=k)
    139             {
    140                 LCM = lcm(abs(A[i][col]),abs(A[k][col]));
    141                 ta = LCM/abs(A[i][col]);
    142                 tb = LCM/abs(A[k][col]);
    143                 if(A[i][col]*A[k][col]<0)tb=-tb;//异号的情况是相加
    144                 for(j=0;j<=var;j++)
    145                 {
    146                     A[i][j] = (A[i][j]*ta - A[k][j]*tb)%p;
    147                 }
    148             }
    149         }
    150     }
    151 
    152   //  Debug(equ,var);
    153 
    154     // 1. 无解的情况: 化简的增广阵中存在(0, 0, ..., a)这样的行(a != 0).
    155     /*
    156     for (i = k; i < equ; i++)
    157     {
    158         if (A[i][col] != 0) return -1;
    159     }
    160     // 对于无穷解来说,如果要判断哪些是自由变元,那么初等行变换中的交换就会影响,则要记录交换.
    161     // 2. 无穷解的情况: 在var * (var + 1)的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵.
    162     // 且出现的行数即为自由变元的个数.
    163     if (k < var)return 1;
    164     {
    165         // 首先,自由变元有var - k个,即不确定的变元至少有var - k个.
    166         for (i = k - 1; i >= 0; i--)
    167         {
    168             // 第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第equ行.
    169             // 同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的.
    170             free_x_num = 0; // 用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元.
    171             for (j = 0; j < var; j++)
    172             {
    173                 if (A[i][j] != 0 && free_x[j]) free_x_num++, free_index = j;
    174             }
    175             if (free_x_num > 1) continue; // 无法求解出确定的变元.
    176             // 说明就只有一个不确定的变元free_index,那么可以求解出该变元,且该变元是确定的.
    177             temp = A[i][var];
    178             for (j = 0; j < var; j++)
    179             {
    180                 if (A[i][j] != 0 && j != free_index) temp -= A[i][j] * x[j];
    181             }
    182             x[free_index] = temp / A[i][free_index]; // 求出该变元.
    183             free_x[free_index] = 0; // 该变元是确定的.
    184         }
    185         return var - k; // 自由变元有var - k个.
    186     }*/
    187     // 3. 唯一解的情况: 在var * (var + 1)的增广阵中形成严格的上三角阵.
    188     // 计算出Xn-1, Xn-2 ... X0.
    189     for (i = var - 1; i >= 0; i--)
    190     {
    191         temp = A[i][var];
    192         for (j = i + 1; j < var; j++)
    193         {
    194             if (A[i][j] != 0) temp = (temp-(A[i][j] * B[j]))%p;
    195         }
    196    //     if (temp % A[i][i] != 0) return -2; // 说明有浮点数解,但无整数解.
    197         int x,y,d;
    198         extgcd(A[i][i],p,d,x,y);
    199         B[i]=((x*(temp/d))%p+p)%p;
    200      //   x[i] = (temp / A[i][i])%p;
    201     }
    202     return 0;
    203 }
    204 
    205 int main()
    206 {
    207  //   freopen("in.txt","r",stdin);
    208     int i,j,t;
    209     char s[N];
    210     scanf("%d",&T);
    211     while(T--)
    212     {
    213         scanf("%d%s",&p,s);
    214         n=strlen(s);
    215         for(i=0;i<n;i++){
    216             t=1;
    217             for(j=0;j<n;j++){
    218                 A[i][j]=t;
    219                 t=(t*(i+1))%p;
    220             }
    221             A[i][j]=s[i]=='*'?0:s[i]-'a'+1;
    222         }
    223 
    224         Gauss(n,n);
    225      //   Debug(n,n);
    226 
    227         printf("%d",B[0]);
    228         for(i=1;i<n;i++)
    229             printf(" %d",B[i]);
    230         putchar('\n');
    231     }
    232     return 0;
    233 }
  • 相关阅读:
    如何用视频云技术,搞一个爆红的 “反应视频” 项目?
    停车场事故频频,AI 达人将摄像头变身安全卫士
    WebRTC 传输安全机制第二话:深入显出 SRTP 协议
    阿里云视频云 Retina 多媒体 AI 体验馆开张啦!
    20 岁发表 SCI 的学霸,梦想用算法改变世界
    阿里绩效考核,简单到不可思议,员工死心塌地跟你干!(转)
    【官方】阿里巴巴合伙人制度全文(转)
    blob视频地址如何下载(转)
    软件开发项目规划时,SA、SD与SE的区别与重要性 【转】
    一分钟看懂公有云和私有云的区别
  • 原文地址:https://www.cnblogs.com/zhsl/p/3109536.html
Copyright © 2020-2023  润新知