zoukankan      html  css  js  c++  java
  • POJ 2497 Widget Factory [高斯消元解同余方程组]

      为了做份高斯消元的模版做了这一题,模版来自http://www.cnblogs.com/kuangbin/archive/2012/08/31/2666144.html。 但这份模版中求自由元的部分应该是错误的,从下向上枚举肯定是不对的,比如x+y+z=10,y+z=5,这个方程组中x实际上是确定的,但这份模版会将x识别为不确定元素。

      其实本来是想找份要求自由元的题目的,但还没找到。这题是求同余方程组,跟一般的高斯消元差不多,只是要在消元过程中注意模的问题,另外最后答案要通过扩展欧几里德求出。

      继续去找要求求自由元的题目。。

      

     1 #include <string.h>
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 #include <algorithm>
     5 #define MAXN 320
     6 #define MOD 7
     7 int n,m,k,tu;
     8 char day[][6]={"MON","TUE","WED","THU","FRI","SAT","SUN"},s1[5],s2[5];
     9 int getday(char *s){
    10     for(int i=0;i<7;i++)if(strcmp(day[i],s)==0)return i;
    11     return -1;
    12 }
    13 //高斯消元解同余线性方程组
    14 int x[MAXN][MAXN],ans[MAXN],fre[MAXN];
    15 void exgcd(int a,int b,int &x,int &y){
    16     b?(exgcd(b,a%b,y,x),y-=x*(a/b)):(x=1,y=0);
    17 }
    18 int gcd(int a,int b){
    19     return b==0?a:gcd(b,a%b);
    20 }
    21 inline int lcm(int x,int y){
    22     return x*y/gcd(x,y);
    23 }
    24 int gauss(int n,int m){//n行m+1列,方程从0,0~n-1,m-1,第m列是常数
    25     memset(ans,0,sizeof ans);
    26     memset(fre,0,sizeof fre);
    27     int row=0,col=0;
    28     for(;row<n&&col<m;col++){
    29         //保证当前行的元素是最大的
    30         int maxr=row;
    31         for(int i=row+1;i<n;i++)if(abs(x[i][col])>abs(x[maxr][col]))maxr=i;
    32         if(maxr!=row)for(int i=0;i<=m;i++)std::swap(x[maxr][i],x[row][i]);
    33         if(x[row][col]==0)continue;
    34         //将下面全部变为0
    35         for(int i=row+1;i<n;i++)
    36          if(x[i][col]!=0){
    37             int g=lcm(abs(x[row][col]),abs(x[i][col])),ga=g/x[row][col],gb=g/x[i][col];
    38             if(x[i][col]*x[row][col]<0)ga=-ga;
    39             for(int j=col;j<=m;j++){
    40                 x[i][j]=(x[i][j]*gb-x[row][j]*ga)%MOD;
    41                 if(x[i][j]<0)x[i][j]+=MOD;
    42             }
    43          }
    44          row++;
    45     }
    46     //判断无解(0,0....a)
    47     for(int i=row;i<n;i++)if(x[i][m]!=0)return -1;
    48     //判断无穷多解,有效方程个数小于未知数数量
    49     if(row<m){
    50         return m-row;
    51     }
    52     //求唯一解
    53     for(int i=m-1;i>=0;i--){
    54         int tmp=0,tx,ty;
    55         for(int j=i+1;j<m;j++)tmp+=ans[j]*x[i][j],tmp%=MOD;
    56         tmp=(x[i][m]-tmp)%MOD;
    57         if(tmp<MOD)tmp+=MOD;
    58         //用扩展欧几里德求解
    59         exgcd(x[i][i],MOD,tx,ty),tx%=MOD;
    60         ans[i]=tx*tmp/gcd(x[i][i],MOD);
    61     }
    62     return 0;
    63 }
    64 
    65 int main(){
    66     freopen("test.in","r",stdin);
    67     while(scanf("%d%d",&n,&m),n||m){
    68         memset(x,0,sizeof x);
    69         for(int i=0;i<m;i++){
    70             scanf("%d%s%s",&k,s1,s2);
    71             while(k--){
    72                 scanf("%d",&tu),x[i][tu-1]++,x[i][tu-1]%=MOD;
    73             }
    74             x[i][n]=((getday(s2)-getday(s1)+1)%MOD+MOD)%MOD;
    75         }
    76         int t=gauss(m,n);
    77         if(t==-1)printf("Inconsistent data.\n");
    78         else if(t>0)printf("Multiple solutions.\n");
    79         else if(t==0){
    80             for(int i=0;i<n;i++){
    81                 ans[i]=(ans[i]%MOD+MOD)%MOD;
    82                 if(ans[i]<3)ans[i]+=7;
    83                 printf("%d%c",ans[i],i==n-1?'\n':' ');
    84             }
    85         }
    86     }
    87     return 0;
    88 }
  • 相关阅读:
    MySQL按照汉字的拼音排序
    js prepend() 和append()区别
    php获取当月天数及当月第一天及最后一天、上月第一天及最后一天实现方法
    (转)对《30个提高Web程序执行效率的好经验》的理解
    打印数组
    php创建文件并写入信息
    关于iOS地图定位中点击设置->隐私->定位服务 闪退问题
    解决WAMP搭建PHP环境后后局域网其他机器无法访问的问题
    用php怎么改文件名
    JSP HTTP 状态码
  • 原文地址:https://www.cnblogs.com/swm8023/p/2667731.html
Copyright © 2011-2022 走看看