P10315 解题报告
题目传送门
题目大意:
有
现给定这
思路:
首先把题面意思抽象出来,令
再令
那么题面就变为了:
再移个项,得:
求出每个
同余只是纸老虎!直接转换成等号,高斯消元求解即可,只是需要把解映射到
同时这道题还需要在无穷多组解时输出任意一组解,需要在消元时额外注意(其实应该只有我这种写法应该注意),不能直接回代求解。
当找到一个主行
这是我原来的高斯消元代码:
int gauss() {
int c, r;
for(c = 0, r = 0; c < n; c++) {
int t = r;
for(int i = r + 1; i < n; i++)
if(abs(a[i][c]) > abs(a[t][c]))
t = i;
if(!a[t][c]) continue;
if(t != r) for(int i = c; i <= n; i++) swap(a[t][i], a[r][i]);
for(int i = n; i >= c; i--) a[r][i] = (a[r][i] * (qpow(a[r][c], mod - 2) + mod) % mod) % mod;
for(int i = r + 1; i < n; i++) //原来是消第 r + 1 到 n 行
if(a[i][c])
for(int j = n; j >= c; j--)
a[i][j] = (mod + a[i][j] - a[i][c] * a[r][j] % mod) % mod;
++r;
}
if(r < n) {
for(int i = r; i < n; i++)
if(a[i][n] > 0)
return -1;
}
for(int i = n - 2; ~i; i--)
for(int j = i + 1; j < n; j++)
a[i][n] = (mod + a[i][n] - a[i][j] * a[j][n] % mod) % mod;
return 1;
}
它在这组数据时会出错:
3 3
2 2 3
2 1 3
1 1
0 0 0
2 1 2
Answer:
0 1 1
或:
1 0 1
My answer:
1 1 0
原矩阵:
这是因为用以上代码消出来的结果为:
而如果直接回代就会直接将
而采用全部重消一遍的方法就能保证所有首变量都只会在一个行向量中出现,这时候回代就完全不用考虑和其他首变量取值出现冲突的问题。
#include <cmath>
#include <iostream>
using namespace std;
const int N = 110;
typedef long long ll;
int n, mod;
ll a[N][N];
ll ans[N];
ll qpow(ll a, int b) {
ll ans = 1, base = a % mod;
while(b) {
if(b & 1) ans = ans * base % mod;
base = base * base % mod;
b >>= 1;
}
return ans;
}
void output() {
puts("---------");
for(int i = 0; i < n; i++) {
for(int j = 0; j <= n; j++)
printf("%d ", a[i][j]);
puts("");
}
puts("---------");
}
int gauss() {
int c, r;
for(c = 0, r = 0; c < n; c++) {
int t = r;
for(int i = r + 1; i < n; i++)
if(abs(a[i][c]) > abs(a[t][c]))
t = i;
if(!a[t][c]) continue;
if(t != r) for(int i = c; i <= n; i++) swap(a[t][i], a[r][i]);
for(int i = n; i >= c; i--) a[r][i] = (a[r][i] * (qpow(a[r][c], mod - 2) + mod) % mod) % mod;
for(int i = 0; i < n; i++) //全部重消一遍
if(a[i][c] && i != r)
for(int j = n; j >= c; j--)
a[i][j] = (mod + a[i][j] - a[i][c] * a[r][j] % mod) % mod; //注意取模时要加上模数以防负数
++r;
}
if(r < n) {
for(int i = r; i < n; i++)
if(a[i][n] > 0)
return -1;
//
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++)
if(a[i][j]) { //寻找首变量
ans[j] = a[i][n]; //直接将首变量赋成方程右侧的值,其他变量都是自由元,直接赋成 0
break;
}
}
return 0;
}
for(int i = n - 2; ~i; i--)
for(int j = i + 1; j < n; j++)
a[i][n] = (mod + a[i][n] - a[i][j] * a[j][n] % mod) % mod;
for(int i = 0; i < n; i++)
ans[i] = a[i][n];
return 1;
}
int main() {
scanf("%d%d", &n, &mod);
ll x;
for(int i = 0; i < n; i++) {
int cnt;
scanf("%d", &cnt);
while(cnt--) {
scanf("%lld", &x);
a[x - 1][i] = 1;
}
a[i][i] = 1;
}
for(int i = 0; i < n; i++)
scanf("%lld", &a[i][n]);
for(int i = 0; i < n; i++) {
scanf("%lld", &x);
a[i][n] = x - a[i][n];
}
int type = gauss();
if(type >= 0)
for(int i = 0; i < n; i++)
printf("%lld ", ans[i]);
else puts("niuza");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具