K - Widget Factory

POJ - 2947

高斯消元求解同余方程组。

首先我们列出方程,注意到这是在\(Mod 7\)意义下成立的方程,因此我们需要把所有操作变为模意义下的操作。

比如我们在消去同一列上其他值时,要用求公倍数消去的方法,最好不要求逆元。

求解时会用到逆元。

注意判断多组解和无解的情况,一个是行数多于列数,有自由元,一个是少于。

注意输出的结果在\([3,9]\)之间。

其他就是写法的问题了,不要写太难看。


#include <iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>

using namespace std;

int gcd(int x,int y) { return !y ? x : gcd(y,x % y); }
int lcm(int x,int y){ return x / gcd(x,y) * y; }

int n,m;

int g[305][305];
int ans[305];

int work(char *a){
    if(a[0] == 'M') return 1;
    if(a[0] == 'W') return 3;
    if(a[0] == 'F') return 5;
    if(a[0] == 'T' && a[1] == 'U') return 2;
    if(a[0] == 'T' && a[1] == 'H') return 4;
    if(a[0] == 'S' && a[1] == 'A') return 6;
    if(a[0] == 'S' && a[1] == 'U') return 7;
}

int inv(int x){
    x %= 7;
    int ret = 1;
    for(int i = 1; i <= 5; ++ i) ret = ret * x % 7;
    return ret;
}

int main() {

while(1){
    scanf("%d%d",&n,&m);
    if(n == 0 && m == 0) break;
    
    memset(g,0,sizeof(g));
    memset(ans,0,sizeof(ans));
    
    for(int i = 1; i <= m; ++ i){
        int s; scanf("%d",&s);
        
        char s1[5],s2[5];
        scanf("%s %s",s1,s2);
        
        g[i][n + 1] = (work(s2) - work(s1) + 8) % 7;
        
        while(s --){
            int x; scanf("%d",&x);
            g[i][x] += 1; g[i][x] %= 7;
        }
    }
    
    int now = 1;
    int flag = 0,pl = 1;
    
    for(int i = 1; i <= n; ++ i, pl = i){
        int ps = now;
        for(int j = now + 1; j <= m; ++ j){
            if(g[ps][i] < g[j][i]) ps = j;
        }
        if(g[ps][i] == 0) continue;
        if(ps != now) for(int j = 1; j <= n + 1; ++ j) swap(g[now][j], g[ps][j]);
        
        for(int j = now + 1; j <= m; ++ j){
        	if(g[j][i] == 0) continue;
            int LCM = lcm(g[now][i],g[j][i]);
            int t1 = LCM / g[now][i]; 
            int t2 = LCM / g[j][i];
            
            for(int k = 1; k <= n + 1; ++ k){
                g[j][k] = (g[j][k] * t2 % 7 - g[now][k] * t1 % 7 + 7) % 7;
            }
        }
        
        ++ now;
    }
    for(int i = now; i <= m; ++ i) if(g[i][pl] != 0) { flag = -1; break; }
    if(flag == 0 && now <= n) { flag = 1; }

    if(flag == -1) { printf("Inconsistent data.\n"); continue; }
    if(flag == 1) { printf("Multiple solutions.\n"); continue; }

	for(int i = now - 1; i >= 1; -- i){
		int temp = g[i][n + 1];
		for(int j = i + 1; j <= n; ++ j) temp += 7 - (g[i][j] * ans[j] % 7), temp %= 7;
		temp = temp * inv(g[i][i]) % 7;
		ans[i] = temp;
	}
	
    for(int i=1;i<=n;i++) { if(ans[i] < 3) ans[i] += 7; printf("%d ",ans[i]); }
    puts("");
}
	return 0;
}


posted @ 2020-07-21 19:37  zhuzihan  阅读(115)  评论(0编辑  收藏  举报