K - Widget Factory
高斯消元求解同余方程组。
首先我们列出方程,注意到这是在\(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;
}