高斯消元

首先,相比于朴素的高斯消元,高斯约旦消元更好写且答案更容易表达,以下代码实现全部采用这种方式

普通的高斯消元通过加减构造上三角矩阵,约旦消元通过加减构造对角线矩阵


传统方程求解

P2455 [SDOI2006]线性方程组

首先是对于多解及无解的判断
如果消元过程中某一列第 \(i\) 行之后都为 \(0\),一定产生一个特殊解
如果是形如 \(0x_i=0\),则有无数组解
如果形如 \(0x_i=a_i\),则无解

以这道题为例附上约旦消元模板


P5027 Barracuda

比较基础的应用,钦定哪个方程是错的,然后消元按照题意判断是否满足条件。


炼金术士的疑惑

一个元素很自然地代表一个未知数
那么可以把最后一个未知数先设为零,消元消元完取反即可


异或方程组

对于异或方程组,操作完全类似,只不过相减变成整行异或,这个一般可以用 \(bitset\) 进行优化

P2447 [SDOI2010]外星千足虫

判断用几个条件可以算出结果,相当于判断除去无用方程(即多解)的凑够 \(n\) 个方程的最后位置


P3164 [CQOI2014]和谐矩阵

将每个位置作为一个未知数,列出上下左右相关方程即可
由于需要输出方案,消成上三角矩阵更为方便


带状矩阵消元

带状矩阵消元可以做到 \(nk^2\) 的复杂度
具体而言暴力消掉对角线下方的东西然后暴力会带即可


CF963E Circles of Waiting

这是模板题


七十

模拟题意写出矩阵可以发现是环带状的,多出来两部分东西,其实只有左下角的有影响,那么每一行都对最后 \(k\) 行消即可
具体实现最好使用 \(STL\)

代码
#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;
}
posted @ 2022-08-09 17:34  y_cx  阅读(91)  评论(0编辑  收藏  举报