[Gauss]POJ2947 Widget Factory

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

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

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

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

 

可以列出同余方程组:$\sum\limits_{i=0}^{n-1} a_i×x_i\equiv 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( \begin{array}{ccc}
1 & 1 & 4 \\
2 & 1 & 5 \\
1 & 2 & 7 \end{array} \right) \to \left( \begin{array}{ccc}
1 & 1 & 4 \\
1 & 0 & 1 \\
0 & 1 & 3 \end{array} \right) \to \left( \begin{array}{ccc}
1 & 0 & 1 \\
0 & 1 & 3 \\
0 & 0 & 0 \end{array} \right)\]

即得$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;

 

完整代码:

[Gauss]POJ2947 Widget Factory
  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.\n");

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("\n");

148                 else

149                     printf(" ");

150             }

151             continue;

152         }

153         printf("Multiple solutions.\n");

154     }

155     return 0;

156 }
POJ 2947

 

你可能感兴趣的:(factory)