zoukankan      html  css  js  c++  java
  • POJ2947 Widget Factory 高斯消元

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

      求解形如:

        a11×x11%p+a12×x12%p+......+a1n×x1n%p=k1%p

        a21×x21%p+a22×x22%p+......+a2n×x2n%p=k2%p

        ......

        an1×xn1%p+an2×xn2%p+......+ann×xnn%p=kn%p

       直接取模求解线性方程组。在网上找了一个整数Gauss的模板,貌似网上很多都是用的这个,但这个模板在多解情况下求变元是否确定有问题,应该用高斯-约当消元求出最简的上三角矩阵:   

         2   1  -1    8                   1   0   0   2
        -3  -1   2  -11   ——>      0   1   0   3 
        -2   1   2   -3                   0   0   1  -1
    那么这样就可以在O(n)的时间内判断变元是否确定。
      1 //STATUS:C++_AC_2657MS_452KB
      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=310;
     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 x[N];//解集
     59 bool free_x[N];//标记是否是不确定的变元
     60 int n,m,k;
     61 
     62 //
     63 void Debug(int equ,int var)
     64 {
     65     int i, j;
     66     for (i = 0; i < equ; i++)
     67     {
     68         for (j = 0; j < var + 1; j++)
     69         {
     70             cout << a[i][j] << " ";
     71         }
     72         cout << endl;
     73     }
     74     cout << endl;
     75 }
     76 //
     77 
     78 inline int gcd(int a,int b)
     79 {
     80     int t;
     81     while(b!=0)
     82     {
     83         t=b;
     84         b=a%b;
     85         a=t;
     86     }
     87     return a;
     88 }
     89 inline int lcm(int a,int b)
     90 {
     91     return a/gcd(a,b)*b;//先除后乘防溢出
     92 }
     93 
     94 // 高斯消元法解方程组(Gauss-Jordan elimination).(-2表示有浮点数解,但无整数解,
     95 //-1表示无解,0表示唯一解,大于0表示无穷解,并返回自由变元的个数)
     96 //有equ个方程,var个变元。增广矩阵行数为equ,分别为0到equ-1,列数为var+1,分别为0到var.
     97 int Gauss(int equ,int var)
     98 {
     99     int i,j,k;
    100     int max_r; // 当前这列绝对值最大的行.
    101     int col; //当前处理的列
    102     int ta,tb;
    103     int LCM;
    104     int temp;
    105     int free_x_num;
    106     int free_index;
    107 
    108     for(int i=0;i<=var;i++)
    109     {
    110         x[i]=0;
    111         free_x[i]=true;
    112     }
    113 
    114     //转换为阶梯阵.
    115     col=0; // 当前处理的列
    116     for(k = 0;k < equ && col < var;k++,col++)
    117     {// 枚举当前处理的行.
    118 // 找到该col列元素绝对值最大的那行与第k行交换.(为了在除法时减小误差)
    119         max_r=k;
    120         for(i=k+1;i<equ;i++)
    121         {
    122             if(abs(a[i][col])>abs(a[max_r][col])) max_r=i;
    123         }
    124         if(max_r!=k)
    125         {// 与第k行交换.
    126             for(j=k;j<var+1;j++) swap(a[k][j],a[max_r][j]);
    127         }
    128         if(a[k][col]==0)
    129         {// 说明该col列第k行以下全是0了,则处理当前行的下一列.
    130             k--;
    131             continue;
    132         }
    133         for(i=0;i<equ;i++)
    134         {// 枚举要删去的行.
    135             if(a[i][col]!=0 && i!=k)
    136             {
    137                 LCM = lcm(abs(a[i][col]),abs(a[k][col]));
    138                 ta = LCM/abs(a[i][col]);
    139                 tb = LCM/abs(a[k][col]);
    140                 if(a[i][col]*a[k][col]<0)tb=-tb;//异号的情况是相加
    141                 for(j=0;j<var+1;j++)
    142                 {
    143                     a[i][j] = ((a[i][j]*ta-a[k][j]*tb)%7+7)%7;
    144                 }
    145             }
    146         }
    147     }
    148 
    149   //  Debug(equ,var);
    150 
    151     // 1. 无解的情况: 化简的增广阵中存在(0, 0, ..., a)这样的行(a != 0).
    152     for (i = k; i < equ; i++)
    153     {
    154         if (a[i][col] != 0) return -1;
    155     }
    156     // 对于无穷解来说,如果要判断哪些是自由变元,那么初等行变换中的交换就会影响,则要记录交换.
    157     // 2. 无穷解的情况: 在var * (var + 1)的增广阵中出现(0, 0, ..., 0)这样的行,即说明没有形成严格的上三角阵.
    158     // 且出现的行数即为自由变元的个数.
    159     if (k < var)return 1;
    160  /*   {
    161         // 首先,自由变元有var - k个,即不确定的变元至少有var - k个.
    162         for (i = k - 1; i >= 0; i--)
    163         {
    164             // 第i行一定不会是(0, 0, ..., 0)的情况,因为这样的行是在第k行到第equ行.
    165             // 同样,第i行一定不会是(0, 0, ..., a), a != 0的情况,这样的无解的.
    166             free_x_num = 0; // 用于判断该行中的不确定的变元的个数,如果超过1个,则无法求解,它们仍然为不确定的变元.
    167             for (j = 0; j < var; j++)
    168             {
    169                 if (a[i][j] != 0 && free_x[j]) free_x_num++, free_index = j;
    170             }
    171             if (free_x_num > 1) continue; // 无法求解出确定的变元.
    172             // 说明就只有一个不确定的变元free_index,那么可以求解出该变元,且该变元是确定的.
    173             temp = a[i][var];
    174             for (j = 0; j < var; j++)
    175             {
    176                 if (a[i][j] != 0 && j != free_index) temp -= a[i][j] * x[j];
    177             }
    178             x[free_index] = temp / a[i][free_index]; // 求出该变元.
    179             free_x[free_index] = 0; // 该变元是确定的.
    180         }
    181         return var - k; // 自由变元有var - k个.
    182     }*/
    183     // 3. 唯一解的情况: 在var * (var + 1)的增广阵中形成严格的上三角阵.
    184     // 计算出Xn-1, Xn-2 ... X0.
    185     /*
    186     for (i = var - 1; i >= 0; i--)
    187     {
    188         temp = a[i][var];
    189         for (j = i + 1; j < var; j++)
    190         {
    191             if (a[i][j] != 0) temp -= a[i][j] * x[j];
    192         }
    193         if (temp % a[i][i] != 0) return -2; // 说明有浮点数解,但无整数解.
    194         x[i] = temp / a[i][i];
    195     }*/
    196     return 0;
    197 }
    198 
    199 map<string,int> q;
    200 
    201 int main()
    202 {
    203 //    freopen("in.txt","r",stdin);
    204     int i,j,num,ans;
    205     char s[10],e[10];
    206     int cnt[N];
    207     q["MON"]=1,q["TUE"]=2,q["WED"]=3,
    208     q["THU"]=4,q["FRI"]=5,q["SAT"]=6,q["SUN"]=7;
    209     while(~scanf("%d%d",&n,&m) && (n || m))
    210     {
    211         for(i=0;i<m;i++){
    212             mem(cnt,0);
    213             scanf("%d%s%s",&k,s,e);
    214             while(k--){
    215                 scanf("%d",&num);
    216                 cnt[num-1]++;
    217             }
    218             for(j=0;j<n;j++)
    219                 a[i][j]=cnt[j]%7;
    220             if(q[s]<=q[e])a[i][n]=(q[e]-q[s]+1)%7;
    221             else a[i][n]=(8-q[s]+q[e])%7;
    222         }
    223      //   Debug(m,n);
    224 
    225         ans=Gauss(m,n);
    226 
    227         if(ans==0){
    228             for(i=0;i<n;i++){
    229                 for(j=3;j<=9;j++)
    230                     if(a[i][i]*j%7==a[i][n]){
    231                         x[i]=j;
    232                         break;
    233                     }
    234             }
    235             printf("%d",x[0]);
    236             for(i=1;i<n;i++)
    237                 printf(" %d",x[i]);
    238         }
    239         else if(ans==-1)printf("Inconsistent data.");
    240         else printf("Multiple solutions.");
    241         putchar('\n');
    242     }
    243     return 0;
    244 }
  • 相关阅读:
    Linux中连接mysql执行sql文件
    各种编码转化
    PHP 创建缩略图
    erlang入门之编译和运行
    mac下的virtualbox启动失败处理
    golang回调函数的例子
    cocos2d-x的popScene的动画效果
    ssdb的golang驱动的同步问题
    贴一段demo代码,演示channel之间的同步
    golang的指针到string,string到指针的转换
  • 原文地址:https://www.cnblogs.com/zhsl/p/3109531.html
Copyright © 2011-2022 走看看