【XSY2777】特征多项式

给一个没有特殊性质的矩阵 \(A\),求其特征多项式 \(|\lambda I-A|\)

定义:若存在一可逆矩阵 \(P\),使得 \(B=PAP^{-1}\),那么称 \(A\)\(B\) 相似,记为 \(A\sim B\)

相似矩阵有很多特殊性质,比如相似矩阵的特征多项式相同。

证明:

首先有 \(\lambda I=\lambda PIP^{-1}=P\lambda IP^{-1}\)

\[\begin{aligned} \det(B)&=|\lambda I -B|\\ &=|\lambda I -PAP^{-1}|\\ &=|P\lambda IP^{-1}-PAP^{-1}|\\ &=|P(\lambda I-A)P^{-1}|\\ &=|P|\times |\lambda I -A|\times |P^{-1}|\\ &=|P\times P^{-1}|\times \det(A)=\det(A) \end{aligned} \]

那么我们对 \(A\) 先进行行变换,记这个行变换对应的初等矩阵为 \(P\),那么我们的操作就是对 \(A\) 左乘 \(P\)

然后我们再对 \(PA\) 右乘 \(P^{-1}\),对应的操作是列变换,然后就能得到 \(B=PAP^{-1}\),显然它与 \(A\) 相似。

具体地说:

  • 若交换矩阵 \(A\) 的第 \(i\) 行和第 \(j\) 行,对应的是交换矩阵 \(A\) 的第 \(i\) 列和第 \(j\) 列。
  • 若将矩阵 \(A\) 的第 \(i\) 行乘上常数 \(k\),对应的是将矩阵 \(A\) 的第 \(i\) 列乘上常数 \(-k\)
  • 若将矩阵 \(A\) 的第 \(i\) 行加上 \(k\) 乘第 \(j\) 行,对应的是将矩阵 \(A\) 的第 \(j\) 列加上 \(-k\) 乘第 \(i\) 列。

推导方式是通过行变换的内容得到左乘的初等矩阵 \(P\),再得到 \(P^{-1}\),再得到右乘 \(P^{-1}\) 的对应的列变换。

但我们不能通过这种方式把 \(A\) 变成上三角矩阵,因为我们在消掉 \((j,i)\) 这个位置的时候,需要让 \(A\) 的第 \(j\) 行加上 \(k\) 乘第 \(i\) 行,此时 \((j,i)\) 变成了 \(0\)。但对应地,我们需要将矩阵 \(A\) 的第 \(i\) 列加上 \(-k\) 乘第 \(j\) 列,这样 \((j,i)\) 又会被受到影响,可能不是 \(0\) 了。

所以我们在消掉 \((j,i)\) 这个位置的时候,用 \(A\) 的第 \(i+1\) 行与第 \(j\) 行做行变换来先把 \((j,i)\) 消掉,这样对应的是 \(A\) 的第 \(i+1\) 列与第 \(j\) 列做列变换,就不会影响到已经消掉的 \((j,i)\) 了。

那么最后得到的就不是上三角矩阵,而是上海森堡矩阵(断句:上/海森堡矩阵):

\[\begin{bmatrix} a_{1,1}&a_{1,2}&a_{1,3}&\cdots&a_{1,n-1}&a_{1,n}\\ a_{2,1}&a_{2,2}&a_{2,3}&\cdots&a_{2,n-1}&a_{2,n}\\ 0&a_{3,2}&a_{3,3}&\cdots&a_{3,n-1}&a_{3,n}\\ 0&0&a_{4,3}&\cdots&a_{4,n-1}&a_{4,n}\\ \vdots&\vdots&\vdots&\ddots&\vdots&\vdots\\ 0&0&0&\cdots&a_{n,n-1}&a_{n,n}\\ \end{bmatrix} \]

那么 \(\lambda I -A\) 为:

\[\begin{bmatrix} \lambda-a_{1,1}&-a_{1,2}&-a_{1,3}&\cdots&-a_{1,n-1}&-a_{1,n}\\ -a_{2,1}&\lambda-a_{2,2}&-a_{2,3}&\cdots&-a_{2,n-1}&-a_{2,n}\\ 0&-a_{3,2}&\lambda-a_{3,3}&\cdots&-a_{3,n-1}&-a_{3,n}\\ 0&0&-a_{4,3}&\cdots&-a_{4,n-1}&-a_{4,n}\\ \vdots&\vdots&\vdots&\ddots&\vdots&\vdots\\ 0&0&0&\cdots&-a_{n,n-1}&\lambda-a_{n,n}\\ \end{bmatrix} \]

\(f_i\) 表示右下角 \(i\times i\) 大小矩阵的行列式,然后就是分类讨论递推了,类似递推方法可以见这道题

而且递推时只涉及多项式加法和多次乘一次的多项式乘法,于是直接暴力存储和运算多项式即可。

#include<bits/stdc++.h>

#define N 510

using namespace std;

namespace modular
{
	const int mod=998244353;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;

inline int poww(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

typedef vector<int> poly;

poly add(poly &a,poly &b,int d)
{
	poly c;
	int sa=a.size(),sb=b.size();
	for(int i=0;i<min(sa,sb);i++)
		c.push_back(add(a[i],mul(d,b[i])));
	if(sa>sb)
	{
		for(int i=sb;i<sa;i++)
			c.push_back(a[i]);
	}
	else
	{
		for(int i=sa;i<sb;i++)
			c.push_back(mul(d,b[i]));
	}
	return c;
}

poly mul(poly &a,poly &b)
{
	int sa=a.size(),sb=b.size();
	poly c(sa+sb-1);
	for(int i=0;i<sa;i++)
		for(int j=0;j<sb;j++)
			c[i+j]=add(c[i+j],mul(a[i],b[j]));
	return c;
}

int n,a[N][N];
poly f[N];

void Gauss()
{
	for(int i=1;i<n;i++)
	{
		int p=i+1;
		for(int j=i+1;j<=n;j++)
			if(a[j][i]>a[p][i]) p=j;
		if(p!=i+1)
		{
			for(int j=1;j<=n;j++)
				swap(a[i+1][j],a[p][j]);
			for(int j=1;j<=n;j++)
				swap(a[j][i+1],a[j][p]);
		}
		for(int j=i+2;j<=n;j++)
		{
			int div=mul(a[j][i],poww(a[i+1][i],mod-2));
			for(int k=1;k<=n;k++)
				a[j][k]=dec(a[j][k],mul(a[i+1][k],div));
			for(int k=1;k<=n;k++)
				a[k][i+1]=add(a[k][i+1],mul(a[k][j],div));
		}
	}
}

int main()
{
	n=read();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			a[i][j]=read();
	Gauss();
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			a[i][j]=dec(0,a[i][j]);
	f[n+1].push_back(1);
	for(int i=n;i>=1;i--)
	{
		poly tmp;
		tmp.push_back(a[i][i]);
		tmp.push_back(1);
		f[i]=mul(tmp,f[i+1]);
		int now=a[i+1][i],c=dec(0,1);
		for(int j=i+1;j<=n;j++)
		{
			f[i]=add(f[i],f[j+1],mul(mul(c,now),a[i][j]));
			now=mul(now,a[j+1][j]);
			c=dec(0,c);
		}
	}
	for(int i=0;i<=n;i++)
		printf("%d ",f[1][i]);
	return 0;
}
posted @ 2022-10-30 10:40  ez_lcw  阅读(151)  评论(0编辑  收藏  举报