(我被这道题恶心了大半个上午)
这道题是一个带mod的高斯消元,所以很明显不能用double类型的数组求解。
那么我们就需要在高斯消元的时候求出两个数的最小公倍数,然后分别乘上一个数以后相减。
接着依次判断无解,多解和只有一组解的情况,最后在求解的时候用乘法逆元(有一个小细节,就是ax=b时,a和b可能一正一负)或者exgcd。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
const int N = 310, P = 7;
int power(int a, int b) {
int ans = 1;
while (b) {
if (b & 1) ans = ans * a % P;
a = a * a % P; b >>= 1;
}
return ans;
}
int n, m, a[N][N], ans[N];
map<string, int> mp;
void init() {
mp["MON"] = 1;
mp["TUE"] = 2;
mp["WED"] = 3;
mp["THU"] = 4;
mp["FRI"] = 5;
mp["SAT"] = 6;
mp["SUN"] = 7;
}
int gcd(int a, int b) { return b != 0 ? gcd(b, a % b) : a;}
void Prepare() {
int k, st, ed; string s;
memset(a, 0, sizeof(a));
for (int i = 1; i <= m; i++) {
scanf("%d", &k);
cin >> s; st = mp[s];
cin >> s; ed = mp[s];
a[i][n + 1] = (ed - st + 1 + P) % P;
for (int j = 1; j <= k; j++) {
scanf("%d", &st);
a[i][st]++; a[i][st] %= P;
}
}
}
void Guass() {
int now = 1; bool flag = 0;
for (int i = 1; i <= n; i++) {
int k = now;
for (; k <= m; k++) if (a[k][i] != 0) break;
if (k == m + 1) continue;
if (k != now) for (int j = 1; j <= n + 1; j++) swap(a[now][j], a[k][j]);
for (int j = 1; j <= m; j++) {
if (j == now) continue;
if (a[j][i] == 0) continue;
int t = a[now][i] * a[j][i] / gcd(a[now][i], a[j][i]);
int p1 = t / a[now][i], p2 = t / a[j][i];
for (int k = 1; k <= n + 1; k++)
a[j][k] = (a[j][k] * p2 - a[now][k] * p1) % P;
}
if (i == n) flag = 1;
now++; if (now == m + 1) break;
}
for (int i = 1; i <= m; i++) {
if (a[i][n + 1] == 0) continue;
bool bk = 0;
for (int j = 1; j <= n; j++)
if (a[i][j] != 0) { bk = 1; break;}
if (!bk) {puts("Inconsistent data."); return;}
}
if (!flag) {puts("Multiple solutions."); return;}
for (int i = 1; i <= n; i++) {
if (a[i][i] == 0) {puts("Multiple solutions."); return;}
if (a[i][i] * a[i][n + 1] < 0) {
if (a[i][i] < 0) a[i][i] = abs(a[i][i]), a[i][n + 1] = abs((a[i][n + 1] % P - P) % P);
else a[i][n + 1] = (a[i][n + 1] % P + P) % P;
}
ans[i] = a[i][n + 1] * power(a[i][i], P - 2) % P;
if (ans[i] < 3) ans[i] += P;
}
for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
puts("");
}
int main() {
init();
while (cin >> n >> m && n && m) {
Prepare();
Guass();
}
return 0;
}