题解:P10315 [SHUPC 2024] 原神,启动!
题目传送门
思路:
假设第
且规定攻击第
我们便可以列出以下方程组:
把左边的
注意到
于是就可以用高斯消元法解方程了。
注意在输出的时候要
Code:
#include <iostream>
#define int long long
using namespace std;
int n, m;
int a[105][105];
inline int upd(int x) {return (x % m + m) % m;}//处理负数
inline int inv(int x) {//保证m为素数,求费马小定理逆元
int res(1), q(m - 2);
while (q) {
if (q & 1) res = res * x % m;
x = x * x % m;
q >>= 1;
}
return res;
}
signed main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
int k;
cin >> k;
a[i][i] = 1;//打自己的时候自己会进入下一个状态
while (k--) {
int x;
cin >> x;
a[x][i] = 1;
}
}
for (int i = 1; i <= n; i++) cin >> a[i][n + 1];//a[i][n + 1]现在存的是s[i]
for (int i = 1, x; i <= n; i++) cin >> x, a[i][n + 1] = upd(x - a[i][n + 1]);//a[i][n + 1]现在存的是t[i]-s[i]
int r(1);
for (int i = 1; i <= n; i++) {
int pos(r);
for (; pos <= n && !a[pos][i]; pos++);
if (pos == n + 1) continue;//第i个未知数被消完
swap(a[r], a[pos]);
int mul(inv(a[r][i]));
for (int j = 1; j <= n; j++) {
if (r != j && a[j][i]) {
for (int k = n + 1; k >= i; k--) {
a[j][k] = upd(a[j][k] - a[r][k] * a[j][i] % m * mul % m);
}
}
}
r++;
}
if (r <= n) {
for (int i = r; i <= n; i++) {//判断无解
bool f(0);
for (int j = 1; j <= n; j++) f |= a[i][j];
if (!f && a[i][n + 1]) cout << "niuza", exit(0);//0==a且a!=0的情况一定无解
}
}
r = 1;
for (int i = 1; i <= n; i++) {
cout << a[r][n + 1] * inv(a[r][i]) % m << ' ';
a[r][n + 1] = 0;
if (!a[r][i + 1]) r++;
}
}
提交记录
点个赞再走罢
Update:
[2024/4/19] 修改
[2024/4/20] 题解被hack,修改了代码。