【XSY2777】特征多项式

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

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

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

证明:

首先有 λ I = λ P I P − 1 = P λ I P − 1 \lambda I=\lambda PIP^{-1}=P\lambda IP^{-1} λI=λPIP1=PλIP1
det ⁡ ( B ) = ∣ λ I − B ∣ = ∣ λ I − P A P − 1 ∣ = ∣ P λ I P − 1 − P A P − 1 ∣ = ∣ P ( λ I − A ) P − 1 ∣ = ∣ P ∣ × ∣ λ I − A ∣ × ∣ P − 1 ∣ = ∣ P × P − 1 ∣ × det ⁡ ( A ) = det ⁡ ( A ) \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} det(B)=λIB=λIPAP1=PλIP1PAP1=P(λIA)P1=P×λIA×P1=P×P1×det(A)=det(A)

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

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

具体地说:

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

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

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

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

那么最后得到的就不是上三角矩阵,而是上海森堡矩阵(断句:上/海森堡矩阵):
[ a 1 , 1 a 1 , 2 a 1 , 3 ⋯ a 1 , n − 1 a 1 , n a 2 , 1 a 2 , 2 a 2 , 3 ⋯ a 2 , n − 1 a 2 , n 0 a 3 , 2 a 3 , 3 ⋯ a 3 , n − 1 a 3 , n 0 0 a 4 , 3 ⋯ a 4 , n − 1 a 4 , n ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 0 ⋯ a n , n − 1 a n , n ] \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} a1,1a2,1000a1,2a2,2a3,200a1,3a2,3a3,3a4,30a1,n1a2,n1a3,n1a4,n1an,n1a1,na2,na3,na4,nan,n
那么 λ I − A \lambda I -A λIA 为:
[ λ − a 1 , 1 − a 1 , 2 − a 1 , 3 ⋯ − a 1 , n − 1 − a 1 , n − a 2 , 1 λ − a 2 , 2 − a 2 , 3 ⋯ − a 2 , n − 1 − a 2 , n 0 − a 3 , 2 λ − a 3 , 3 ⋯ − a 3 , n − 1 − a 3 , n 0 0 − a 4 , 3 ⋯ − a 4 , n − 1 − a 4 , n ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 0 ⋯ − a n , n − 1 λ − a n , n ] \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} λa1,1a2,1000a1,2λa2,2a3,200a1,3a2,3λa3,3a4,30a1,n1a2,n1a3,n1a4,n1an,n1a1,na2,na3,na4,nλan,n
f i f_i fi 表示右下角 i × i i\times i i×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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值