• K


    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.
    "); continue; }
        if(flag == 1) { printf("Multiple solutions.
    "); 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;
    }
    
    
    
  • 相关阅读:
    指针数组和数组指针表示二维数组
    scanf与getchar()区别
    选择循环
    朴素的思想
    asp.net中word转html碰到的权限异常问题(转)
    MAC下安装Fiddler抓包工具
    抓包工具charles的使用
    mysql 命令大全
    利用反射拼接SQL查询条件字符串
    赚自己的淘宝佣金,让返利网无路可走
  • 原文地址:https://www.cnblogs.com/zzhzzh123/p/13357018.html
Copyright © 2020-2023  润新知