学习笔记 矩阵的特征多项式 & 快速矩阵快速幂
定理:相似矩阵特征多项式相同。
证明:
考虑如何求出矩阵特征多项式。
朴素的消元方法由于涉及多项式运算,复杂度显然高于
实对称阵可以相似对角化,但一般数域上的矩阵并不都能相似对角化,但可以消成如下类似对角矩阵的形式。
方法:构造初等矩阵
则用
化成如上矩阵后,可以轻易计算特征多项式。
考虑递推求解前
观察矩阵可以发现,选取位于
于是我们可以
用途:写奇怪的
据说可以加速矩阵快速幂,先咕着。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=502,p=998244353;
int a[N][N],f[N];
int n,i,j,k,x,y,r,q;
template<typename typC> void read(register typC &x)
{
register int c=getchar(),fh=1;
while ((c<48)||(c>57))
{
if (c=='-') {c=getchar();fh=-1;break;}
c=getchar();
}
x=c^48;c=getchar();
while ((c>=48)&&(c<=57))
{
x=x*10+(c^48);
c=getchar();
}
x*=fh;
}
inline void inc(register int &x,const int y)
{
if ((x+=y)>=p) x-=p;
}
inline void dec(register int &x,const int y)
{
if ((x-=y)<0) x+=p;
}
inline int ksm(register int x,register int y)
{
register int r=1;
while (y)
{
if (y&1) r=(ll)r*x%p;
x=(ll)x*x%p;y>>=1;
}
return r;
}
void calmatrix(int a[N][N],register int n)
{
register int i,j,k,r;
for (i=2;i<=n;i++)
{
for (j=i;j<=n&&!a[j][i-1];j++);
if (j>n) {continue;}
if (j>i)
{
swap(a[i],a[j]);//exit(-1);
for (k=1;k<=n;k++) swap(a[k][j],a[k][i]);
}
r=a[i][i-1];
for (j=1;j<=n;j++) a[j][i]=(ll)a[j][i]*r%p;
r=ksm(r,p-2);
for (j=i-1;j<=n;j++) a[i][j]=(ll)a[i][j]*r%p;
for (j=i+1;j<=n;j++)
{
r=a[j][i-1];
for (k=1;k<=n;k++) a[k][i]=(a[k][i]+(ll)a[k][j]*r)%p;
r=p-r;
for (k=i-1;k<=n;k++) a[j][k]=(a[j][k]+(ll)a[i][k]*r)%p;
}
}
}
void calpoly(int a[N][N],register int n,int *f)
{
static int g[N][N];
memset(g,0,sizeof(g));
g[0][0]=1;
register int i,j,k,r,rr;
for (i=1;i<=n;i++)
{
r=p-1;
for (j=i;j;j--)//第 j 行选第 n 列
{
rr=(ll)r*a[j][i]%p;
for (k=0;k<j;k++) g[i][k]=(g[i][k]+(ll)rr*g[j-1][k])%p;
r=(ll)r*a[j][j-1]%p;
}
for (k=1;k<=i;k++) inc(g[i][k],g[i-1][k-1]);
}
memcpy(f,g[n],n+1<<2);
// if (n&1) for (i=0;i<=n;i++) if (f[i]) f[i]=p-f[i];//这题特殊(A-kE),否则注释掉
}
int main()
{
read(n);//read(q);
for (i=1;i<=n;i++) for (j=1;j<=n;j++) read(a[i][j]);
calmatrix(a,n);calpoly(a,n,f);
for (i=0;i<=n;i++) printf("%d%c",f[i]," \n"[i==n]);
}