zoukankan      html  css  js  c++  java
  • [Gauss]POJ2947 Widget Factory

    题意: 有n种小工具要加工,每种工具的加工时间为3到9天,给了m条加工记录。

        每条记录 X $s_1$ $s_2$ 分别代表 这个工人在$s_1$到$s_2$(前闭后闭)的时间里加工了X件小工具 

        下一行给出这X件小工具的种类

      要求的是每件工具的加工时间 (唯一解:输出各个时间;无解:Inconsistent data.;多个解:Multiple solutions.)

    可以列出同余方程组:$sumlimits_{i=0}^{n-1} a_i×x_iequiv T pmod{7}$

              ($a_i$是此人加工第i件物品的个数,$x_i$是第i件物品加工所需的时间,T是此人干活的时间)

         这样列出m个同余方程 组成方程组 用高斯消元

    比如第一个案例:

    2 3
    2 MON THU
    1 2
    3 MON FRI
    1 1 2
    3 MON SUN
    1 2 2

    可以列出方程组:  

    1×$x_0$+1×$x_1 equiv 4 pmod{7}$

    2×$x_0$+1×$x_1 equiv 5 pmod{7}$

    1×$x_0$+2×$x_1 equiv 7 pmod{7}$

    [ left( egin{array}{ccc}
    1 & 1 & 4 \
    2 & 1 & 5 \
    1 & 2 & 7 end{array} ight) o left( egin{array}{ccc}
    1 & 1 & 4 \
    1 & 0 & 1 \
    0 & 1 & 3 end{array} ight)  o left( egin{array}{ccc}
    1 & 0 & 1 \
    0 & 1 & 3 \
    0 & 0 & 0 end{array} ight)]

    即得$x_0$=1,$x_1$=3
    由题意 每种工具的加工时间为3到9天
    故 $x_0$=8,$x_1$=3
    解毕


    下面是代码:

    有mod就会有要求逆元
    两种求逆元的方法

    1. extend gcd
    注意得到的x可能为负 要x=(x%mod+mod)%mod;
     1 void ex_gcd(int a, int b, int &x, int &y)
     2 {
     3     if(b)
     4     {
     5         ex_gcd(b, a%b, x, y);
     6         int tmp=x;
     7         x=y;
     8         y=tmp-(a/b)*y;
     9     }
    10     else
    11     {
    12         x=1, y=0;
    13         return ;
    14     }
    15 }

    2.inverse element

    注意  只适用于a<b 并且 ab互质

    1 int inv(int a, int b)
    2 {
    3     return a==1? 1:inv(b%a, b)*(b-b/a)%b;
    4 }

    此题还有一法不求逆元:(利用欧拉函数)

    即 把被除数不断加上mod 直到它能被除数整除为止

     1 while(tmp%a[i][i])
     2      tmp+=mod;
     3 x[i]=(tmp/a[i][i])%mod;
     4 
     5 与以下等价
     6 
     7 int xx, yy;
     8 ex_gcd(a[i][i], mod, xx, yy);
     9 xx=(xx%mod+mod)%mod;
    10 x[i]=(tmp*xx)%mod;
    11 
    12 与以下等价
    13 
    14 x[i]=(tmp*inv(a[i][i], mod))%mod;

    完整代码:

      1 const int mod=7;
      2 int gcd(int a, int b)
      3 {
      4     return b==0? a:gcd(b, a%b);
      5 }
      6 int lcm(int a, int b)
      7 {
      8     return a/gcd(a, b)*b;
      9 }
     10 void ex_gcd(int a, int b, int &x, int &y)
     11 {
     12     if(b)
     13     {
     14         ex_gcd(b, a%b, x, y);
     15         int tmp=x;
     16         x=y;
     17         y=tmp-(a/b)*y;
     18     }
     19     else
     20     {
     21         x=1, y=0;
     22         return ;
     23     }
     24 }
     25 
     26 int a[300][300];  // 增广矩阵
     27 int x[300];  //
     28 int free_x[300]; // 标记是否为自由未知量
     29 
     30 int Gauss(int n, int m) // n个方程 m个未知数 即 n行m+1列
     31 {
     32     //转换为阶梯形式
     33     int col=0, k, num=0;
     34     for(k=0;k<n && col<m;k++, col++)
     35     {//枚举行
     36         int max_r=k;
     37         for(int i=k+1;i<n;i++)//找到第col列元素绝对值最大的那行与第k行交换
     38             if(abs(a[i][col])>abs(a[max_r][col]))
     39                 max_r=i;
     40         if(max_r!=k)// 与第k行交换
     41             for(int j=col;j<m+1;j++)
     42                 swap(a[k][j], a[max_r][j]);
     43         if(!a[k][col])// 说明该col列第k行以下全是0了
     44         {
     45             k--;
     46             free_x[num++]=col;
     47             continue;
     48         }
     49         for(int i=k+1;i<n;i++)// 枚举要删除的行
     50             if(a[i][col])
     51             {
     52                 int LCM=lcm(abs(a[i][col]), abs(a[k][col]));
     53                 int ta=LCM/abs(a[i][col]);
     54                 int tb=LCM/abs(a[k][col]);
     55                 if(a[i][col]*a[k][col]<0)
     56                     tb=-tb;
     57                 for(int j=col;j<m+1;j++)
     58                     a[i][j]=((a[i][j]*ta-a[k][j]*tb)%mod+mod)%mod;
     59             }
     60     }
     61 
     62     for(int i=k;i<n;i++)
     63         if(a[i][col])
     64             return -1; // 无解
     65 
     66     if(k<m)   //m-k为自由未知量个数
     67         return m-k;
     68 
     69     //  唯一解 回代
     70     for(int i=m-1;i>=0;i--)
     71     {
     72         int tmp=a[i][m];
     73         for(int j=i+1;j<m;j++)
     74         {
     75             if(a[i][j])
     76                 tmp-=a[i][j]*x[j];
     77             tmp=(tmp%7+7)%7;
     78         }
     79         int xx, yy;
     80         ex_gcd(a[i][i], mod, xx, yy);
     81         xx=(xx%mod+mod)%mod;
     82         x[i]=(tmp*xx)%mod;
     83     }
     84     return 0;
     85 }
     86 
     87 
     88 void init()
     89 {
     90     memset(a, 0, sizeof(a));
     91     memset(x, 0, sizeof(x));
     92 }
     93 
     94 int change(char c1, char c2)
     95 {
     96     if(c1=='M')
     97         return 1;
     98     if(c1=='T' && c2=='U')
     99         return 2;
    100     if(c1=='W')
    101         return 3;
    102     if(c1=='T')
    103         return 4;
    104     if(c1=='F')
    105         return 5;
    106     if(c1=='S' && c2=='A')
    107         return 6;
    108     return 7;
    109 }
    110 
    111 char s1[10], s2[10];
    112 int main()
    113 {
    114     int n, m;
    115     while(~scanf("%d%d", &n, &m))
    116     {
    117         if(!n && !m)
    118             break;
    119         init();
    120         for(int i=0;i<m;i++)
    121         {
    122             int X;
    123             scanf("%d%s%s", &X, s1, s2);
    124             a[i][n]=((change(s2[0], s2[1])-change(s1[0], s1[1])+1)%mod+mod)%mod;
    125             while(X--)
    126             {
    127                 int t;
    128                 scanf("%d", &t);
    129                 a[i][t-1]=(a[i][t-1]+1)%mod;
    130             }
    131         }
    132         int t=Gauss(m, n);
    133         if(t==-1)
    134         {
    135             printf("Inconsistent data.
    ");
    136             continue;
    137         }
    138         if(t==0)
    139         {
    140             for(int i=0;i<n;i++)
    141                 if(x[i]<=2)
    142                     x[i]+=7;
    143             for(int i=0;i<n;i++)
    144             {
    145                 printf("%d", x[i]);
    146                 if(i==n-1)
    147                     printf("
    ");
    148                 else
    149                     printf(" ");
    150             }
    151             continue;
    152         }
    153         printf("Multiple solutions.
    ");
    154     }
    155     return 0;
    156 }
    POJ 2947
  • 相关阅读:
    PHP 数组和字符串转换(超详细
    获取客户端ip、地理信息、浏览器、真实IP的php类库
    将博客搬至CSDN
    1.0.1unity服务器学习经验
    音游制作插件Koreographer-第0篇 简介
    Unity UIWidgets
    Unity UIWidgets
    Unity UIWidgets
    Lua中ipairs和pairs的区别详解
    ubuntu下面配置apache
  • 原文地址:https://www.cnblogs.com/Empress/p/4249444.html
Copyright © 2011-2022 走看看