UVA 1564 & SPOJ 2883 题解

双倍经验:UVA \(\quad\)SPOJ

两道题是一模一样的,算是水紫吧。但是我就是调了快半天才过(果然还是我太菜了)。

由题意我们很容易列出下面的方程:

\(\begin{cases}\sum_{i=1}^na_{1_i}x_1 \equiv b_1\pmod{7}\\\sum_{i=1}^na_{2_i}x_1 \equiv b_2\pmod{7}\\\cdots \cdots\\\sum_{i=1}^na_{m_i}x_1 \equiv b_m\pmod{7}\end{cases}\)

发现这是一个线性方程组,考虑使用高斯消元求解。直接套板子就行了,不同的是以下几点:

1、除法是在模意义下进行的,要取逆元。但是这道题的模数甚至只有 \(7\):写不写快速幂都差不多(常数差距了属于是)

2、判断无解、多解时:

如果方程数量大于未知数个数,消完后前 \(n\) 个式子都形如 \(a\times x\equiv b\) 而后面的式子各项系数都为 \(0\)(想想高斯消元是怎么晓得)。此时如果一个式子的值不为 \(0\) 则方程一定无解

如果消出来后主元个数小于 \(n\) 有多组解(这很显然吧)。

最后,我们得到了一堆形如 \(a\times x\equiv b\) 的式子,\(x\) 的取值范围三到九。你甚至还是可以暴力算,写不写 \(exgcd\) 都行(说不定跑的比你递归快呢)。记得这一步也要判无解。

代码挺好写的吧,不知道为什么别的题解都写了一百多行,其实只用 \(25\) 行就够了,好像也没有怎么压行吗(-xlpg0713)

#include<bits/stdc++.h>
using namespace std;
int n, m, a[301][302], res[301]; map<string, int>mp;
inline int inv(int x){int rs=1;for(int i=1;i<=5;i++)rs*=x;return rs%7;} //真.循环求逆元
inline void solve(){ int cnt = 0;
    for(int i = 1, tmp = 0; i <= n; i++, tmp = 0){
        for(int j = cnt + 1; j <= m; j++) if(a[j][i]) tmp = j;
        if(!tmp) continue; swap(a[++cnt], a[tmp]);
        for(int j = 1; j <= m; j++)if(j!=cnt){int d=(-a[j][i]*inv(a[cnt][i])%7+7)%7;
            for(int k = 1; k <= n + 1; k++) (a[j][k] += a[cnt][k] * d) %= 7;} //长达四行的高斯消元
    }for(int i=cnt+1;i<=m;i++)if(a[i][n+1]%=7)return void(cout<<"Inconsistent data.\n"); //case 1
    if(cnt < n) return void(cout << "Multiple solutions.\n"); //case 2
    for(int i = 1; i <= n; i++){res[i] = 0; for(int j = 3; j <= 9; j++) 
    if(a[i][i]*j%7==a[i][n+1])res[i]=j;if(!res[i])return void(cout<<"Inconsistent data.\n");} //case 3
    for(int i = 1; i < n; i++) cout << res[i] << ' '; cout << res[n] << '\n'; //UVA的特殊格式(确信)
}
int main(){ mp["MON"]=1,mp["TUE"] = 2,mp["WED"] = 3,
    mp["THU"]=4,mp["FRI"]=5,mp["SAT"]=6,mp["SUN"]=7; //算日期,为了压行甚至不写函数
    while(cin >> n >> m && n && m){
        for(int i = 1; i <= m; i++) for(int j = 1; j <= n + 1; j++) a[i][j] = 0;
        for(int i = 1; i <= m; i++){ int k, x; string s, t; cin >> k >> s >> t;
            a[i][n + 1] = (mp[t] - mp[s]+8)%7;while(k--){cin>>x;a[i][x]++;a[i][x]%=7;} //列方程
        } solve();
    }
}
posted @ 2023-10-01 01:06  xlpg0713  阅读(13)  评论(0)    收藏  举报