高斯消元
首先,相比于朴素的高斯消元,高斯约旦消元更好写且答案更容易表达,以下代码实现全部采用这种方式
普通的高斯消元通过加减构造上三角矩阵,约旦消元通过加减构造对角线矩阵
传统方程求解
首先是对于多解及无解的判断
如果消元过程中某一列第 行之后都为 ,一定产生一个特殊解
如果是形如 ,则有无数组解
如果形如 ,则无解
以这道题为例附上约旦消元模板
比较基础的应用,钦定哪个方程是错的,然后消元按照题意判断是否满足条件。
一个元素很自然地代表一个未知数
那么可以把最后一个未知数先设为零,消元消元完取反即可
异或方程组
对于异或方程组,操作完全类似,只不过相减变成整行异或,这个一般可以用 进行优化
判断用几个条件可以算出结果,相当于判断除去无用方程(即多解)的凑够 个方程的最后位置
将每个位置作为一个未知数,列出上下左右相关方程即可
由于需要输出方案,消成上三角矩阵更为方便
带状矩阵消元
带状矩阵消元可以做到 的复杂度
具体而言暴力消掉对角线下方的东西然后暴力会带即可
这是模板题
模拟题意写出矩阵可以发现是环带状的,多出来两部分东西,其实只有左下角的有影响,那么每一行都对最后 行消即可
具体实现最好使用 等
代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
using namespace std;
using namespace __gnu_pbds;
//#define int long long
const int maxn=2e4+5;
cc_hash_table <int,long long>a[maxn];
int sta[maxn],tp,l[maxn],r[maxn],n,k;
//#define int long long
#define fi first
#define se second
const int mod=998244353;
long long ans[maxn],sum;
int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int po(int a,int b=mod-2){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return ans;
}
void print(){
puts("hhh");
for(int i=1;i<=n;i++){
for(int j=1;j<=n+1;j++)cout<<a[i][j]<<" ";
puts("");
}
}
void gauss(){
for(int i=1;i<=n;i++){
long long w=po(a[i][i]);
for(auto x:a[i])if(!x.se)sta[++tp]=x.fi;
while(tp)a[i].erase(sta[tp--]);
for(auto &x:a[i])x.se=x.se*w%mod;
for(int j=min(n,i+k);j>=i+1;j--){
if(a[j].find(i)==a[j].end())continue;
w=a[j][i];
for(auto x:a[i])a[j][x.fi]=(a[j][x.fi]-w*x.se)%mod;
}
for(int j=max(i+1,n-k);j<=n;j++){
if(a[j].find(i)==a[j].end())continue;
w=a[j][i];if(!w)continue;
for(auto x:a[i])a[j][x.fi]=(a[j][x.fi]-w*x.se)%mod;
}
}
for(int i=n;i>=1;i--){
ans[i]=a[i][n+1];
for(auto x:a[i]){
if(x.fi<=n&&x.fi!=i){
(ans[i]-=x.se*ans[x.fi]%mod)%=mod;
}
}
}
return ;
}
signed main(){
// freopen("ex_seventy3.in","r",stdin);
freopen("seventy.in","r",stdin);
freopen("seventy.out","w",stdout);
n=read(),k=read();
for(int i=1;i<=n;i++){
sum=0;
for(int j=k;j>=1;j--)(sum+=l[j]=read())%=mod;
for(int j=1;j<=k;j++)(sum+=r[j]=read())%=mod;
a[i][i]=1;sum=po(sum);
for(int j=1;j<=k;j++){
((a[(i-j+n-1)%n+1][i]-=l[j]*sum%mod))%=mod;
((a[(i+j-1)%n+1][i]-=r[j]*sum%mod))%=mod;
}
}
for(int i=1;i<=n+1;i++)a[n][i]=1;
// print();
gauss();
for(int i=1;i<=n;i++)printf("%d\n",(ans[i]+mod)%mod);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2021-08-09 noip模拟34