蓝书(算法竞赛进阶指南)刷题记录——POJ2947 Widget Factory(带模高斯消元)

题目:POJ2947.
题目大意:有 n n n种部件,每种部件生产一个的时间为 3 3 3~ 9 9 9天.现在给定 m m m条记录,每个记录为某种 k i k_i ki个部件的生产时间为星期几 s i s_i si到星期几 t i t_i ti,以及这 k i k_i ki个部件的类型,问每种部件单个生产所需的时间.若无解输出"Inconsistent data.",有多组解输出"Multiple solutions.".
1 ≤ n , m ≤ 300 , 1 ≤ ∑ k i ≤ 1 0 4 1\leq n,m\leq 300,1\leq \sum k_i\leq 10^4 1n,m300,1ki104.

我们考虑设每个部件单个生产所需的时间为 x i x_i xi,第 i i i条记录中第 j j j种部件的数量为 a i , j a_{i,j} ai,j,那么可以列出一下方程组:
{ a 1 , 1 x 1 + a 1 , 2 x 2 + ⋯ + a 1 , n x n = t 1 − s 1    ( m o d    7 ) a 2 , 1 x 2 + a 2 , 2 x 2 + ⋯ + a 2 , n x n = t 2 − s 2    ( m o d    7 ) ⋮ a m , 1 x 1 + a m , 2 x 2 + ⋯ + a m , n x n = t m − s m    ( m o d    7 ) \left\{\begin{matrix} a_{1,1}x_1+a_{1,2}x_2+\cdots+a_{1,n}x_n=t_1-s_1\,\,(mod\,\,7)\\ a_{2,1}x_2+a_{2,2}x_2+\cdots+a_{2,n}x_n=t_2-s_2\,\,(mod\,\,7)\\ \vdots\\ a_{m,1}x_1+a_{m,2}x_2+\cdots+a_{m,n}x_n=t_m-s_m\,\,(mod\,\,7) \end{matrix}\right. a1,1x1+a1,2x2++a1,nxn=t1s1(mod7)a2,1x2+a2,2x2++a2,nxn=t2s2(mod7)am,1x1+am,2x2++am,nxn=tmsm(mod7)

这是一个典型的带模高斯消元,只是最后得到的解需要通过 ± 7 \pm7 ±7控制在 3 3 3~ 9 9 9范围内.

考虑高消时我们只需要把它消成一个三角矩阵,所以每当我们要处理第 i i i行第 j j j列的元素时,只需要把第 j j j列整一列的元素中,除了第 i i i行的全部消为 0 0 0.

这个时候若要消掉第 k k k行,我们只需要让第 k k k行同乘以 a [ i ] [ j ] a[i][j] a[i][j]且让第 i i i行同乘以 a [ k ] [ j ] a[k][j] a[k][j]来消元即可.

最后求解的时候由于系数不为 1 1 1,我们可以直接用费马小定理求解逆元.

解的情况判定与普通高斯消元类似.整个算法的时间复杂度为 O ( n 2 m ) O(n^2m) O(n2m).

注意,这种算法只能用于模数为质数的情况下.当模数为非质数时,这种算法会在同乘以一个数的地方出错.

代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int mod=7,N=300;

int n,m,flag,ans[N+9];
struct matrix{
  int n,m,v[N+9][N+9];
}a;

int ri(){
  int x=0;
  char c=getchar();
  for (;c<'0'||c>'9';c=getchar());
  for (;c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
  return x;
}

int rc(){
  char c1=getchar(),c2;
  while (c1<'A'||c1>'Z') c1=getchar();
  c2=getchar();getchar();
  if (c1=='T') return c2=='U'?2:4;
  if (c1=='S') return c2=='A'?6:7;
  if (c1=='M') return 1;
  return c1=='F'?5:3;
}

int print(int x){
  x%=mod;
  if (x<3) x+=mod;
  printf("%d ",x);
}

int power(int a,int k){
  int s=1;
  for (;k;k>>=1,a=a*a%mod)
    if (k&1) s=s*a%mod;
  return s;
}

int Gauss(matrix a){
  int n=a.n,m=a.m,now=1,r,x,y;
  for (int i=1;i<=n;++i){
  	for (r=now;r<=m;++r)
  	  if (a.v[r][i]) break;
  	if (r>m) continue;
  	if (r^now) swap(a.v[r],a.v[now]);
	x=a.v[now][i];
  	for (int j=1;j<=m;++j)
  	  if (now^j){
  	  	y=a.v[j][i];
  	  	for (int k=1;k<=n+1;++k)
  	  	  a.v[j][k]=((a.v[j][k]*x-a.v[now][k]*y)%mod+mod)%mod;
	  }
	++now;
  }
  for (int i=1;i<=n;++i)
    ans[i]=a.v[i][n+1]*power(a.v[i][i],mod-2)%mod;
  for (int i=now;i<=m;++i)
    if (a.v[i][n+1]) return 0;
  return now<=n?2:1;
}

Abigail into(){
  a=matrix();
  a.n=n;a.m=m;
  int k,x,y;
  for (int i=1;i<=m;++i){
  	k=ri();x=rc();y=rc()-x+1;
  	a.v[i][n+1]=(y%mod+mod)%mod;
  	for (int j=1;j<=k;++j)
  	  ++a.v[i][ri()];
  	for (int j=1;j<=n;++j)
  	  a.v[i][j]%=mod;
  }
}

Abigail work(){
  flag=Gauss(a);
}

Abigail outo(){
  if (flag==0) puts("Inconsistent data.");
  else if (flag==2) puts("Multiple solutions.");
    else{
      for (int i=1;i<=n;++i)
        print(ans[i]);
      puts("");
	}
}

int main(){
  while (2333){
  	n=ri();m=ri();
  	if (n+m==0) return 0;
    into();
    work();
    outo();
  }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值