矩阵的特征值分解

引入问题:给定一个对角线非零的上三角矩阵\(M\),求\(M^k\),满足\(M\)的阶\(\le 500\),\(k\le 10^9\)。

对998244353取模。

一个显而易见的算法是矩阵快速幂,然而是\(O(N^3\log k)\)的,无法通过本题。

一开始我想,既然是上三角矩阵,那么特征多项式一定不难求,那么是用CH定理+FFT多项式取模啥搞搞?

然而我naive了。

这题我们可以把\(M\)特征值分解为\(Q^{-1}AQ\)形式,其中\(A\)是一个对角矩阵。

那么\(M^k=(Q^{-1}AQ)^k=Q^{-1}A^kQ\)。

对一个对角矩阵进行幂的复杂度是\(N\log C\)的,矩阵乘法的复杂度是\(O(N^3)\)的,对一个上三角矩阵进行特征值分解可以使用高斯消元,时间复杂度也是\(O(N^3)\),具体怎么对上三角矩阵进行特征值分解??我tm怎么知道,这个得好好研究一下

upd

自己手推没推出来。观察了下std,手跑了下样例,得出来一些性质。

矩阵\(Q^{-1}\)的第\(i\)列,即为矩阵\(M\)对应第\(i\)行第\(i\)列特征值的特征向量。

这个性质通过特征值分解那套理论也不难得到--因为特征向量是\(M\)所对应“方向不变”的向量,而\(Q\)和\(Q^{-1}\)就是在这些旋转方向上的向量,通过线性变换把它们旋转过去//线代那套理论太玄学

std里在\(Q^{-1}\)上递推的,没有看得非常透彻(不过大致也观察出了一些什么),目前已经观察得比较透彻了。

求出\(Q^{-1}\)后直接上矩阵求逆板子求\(Q\),然后直接矩阵乘法就行了。

代码如下:

#include <cstdio>
using namespace std;

const int p = 998244353;

int n, k, a[500][500], l[500][500], r[500][500], v[500];

int qpow(int x, int y)
{
    int res = 1;
    for (x %= p; y > 0; y >>= 1, x = x * (long long)x % p)
        if (y & 1) res = res * (long long)x % p;
    return res;
}

int main()
{
    scanf("%d%d", &n, &k);
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
            scanf("%d", &a[i][j]);

    //求l
    for (int i = 0; i < n; i++) //枚举l矩阵的第i列,为a矩阵对应于aii的特征向量
    {
        l[i][i] = 1; //钦定的
        for (int j = i - 1; j >= 0; j--) //求这个特征向量的第j行的值
        {
            int sum = 0; //这里需要满足的是\sum_{k=0}^{n-1}a_{j,k}*l{k,i}=0,此时求值为$b_{ji}$
            for (int k = j + 1; k <= i; k++)
                sum = (sum + a[j][k] * (long long)l[k][i]) % p;
            l[j][i] = sum * (long long)qpow((a[i][i] - a[j][j] + p) % p, p - 2) % p;
            //注意这里是a[i][i] - a[j][j], 相当于乘了个-1,就是我们要求的值了
        }
    }

    //求l的逆矩阵r,注意到l是上三角矩阵
    for (int i = n - 1; i >= 0; i--)
    {
        r[i][i] = qpow(l[i][i], p - 2);
        for (int j = 0; j < i; j++)
        {
            int e = l[j][i] * (long long)qpow(l[j][j], p - 2) % p;
            for (int k = i; k < n; k++)
                r[j][k] = ((r[j][k] - r[i][k] * (long long)e % p) % p + p) % p;
        }
    }

    //收集答案
    for (int i = 0; i < n; i++) v[i] = qpow(a[i][i], k);

    long long ans1 = 0, ans2 = 0;

    for (int i = 0; i < n; i++)
        for (int j = i; j < n; j++)
        {
            int sb = 0;
            for (int k = i; k <= j; k++)
                sb = (sb + l[i][k] * (long long)v[k] % p * r[k][j] % p) % p;
            ans1 += sb, ans2 ^= sb;
        }
    printf("%lld %lld\n", ans1, ans2);
    return 0;
}

以后再研究下一般矩阵的特征值分解,就可以弄图片压缩啥的了。

这个代码常数略大,本来可以弄小一点的

把最后收集答案时候先让对角矩阵和l乘一下再收集、以及优化一下(x%p+p)%p那部分即可。

原文地址:https://www.cnblogs.com/oier/p/10291286.html

时间: 2024-07-30 10:54:14

矩阵的特征值分解的相关文章

矩阵的“特征值分解”和“奇异值分解”区别

在信号处理中经常碰到观测值的自相关矩阵,从物理意义上说,如果该观测值是由几个(如 K 个)相互统计独立的源信号线性混合而成,则该相关矩阵的秩或称维数就为 K,由这 K 个统计独立信号构成 K 维的线性空间,可由自相关矩阵最大 K 个特征值所对应的特征向量或观测值矩阵最大 K 个奇异值所对应的左奇异向量展成的子空间表示,通常称信号子空间,它的补空间称噪声子空间,两类子空间相互正交.理论上,由于噪声的存在,自相关矩阵是正定的,但实际应用时,由于样本数量有限,可能发生奇异,矩阵条件数无穷大,造成数值不

矩阵的特征值分解和奇异值分解

定理:(奇异值分解)设A为m*n阶复矩阵,则存在m阶酉阵U和n阶酉阵V,使得: A = U*S*V’ 其中S=diag(σi,σ2,……,σr),σi>0 (i=1,…,r),r=rank(A). 推论:设A为m*n阶实矩阵,则存在m阶正交阵U和n阶正交阵V,使得 A = U*S*V’ 其中S=diag(σi,σ2,……,σr),σi>0 (i=1,…,r),r=rank(A). 1.奇异值分解非常有用,对于矩阵A(m*n),存在U(m*m),V(n*n),S(m*n),满足A = U*S*V

矩阵的SVD分解

转自 http://blog.csdn.net/zhongkejingwang/article/details/43053513(实在受不了CSDN的广告) 在网上看到有很多文章介绍SVD的,讲的也都不错,但是感觉还是有需要补充的,特别是关于矩阵和映射之间的对应关系.前段时间看了国外的一篇文章,叫A Singularly Valuable Decomposition The SVD of a Matrix,觉得分析的特别好,把矩阵和空间关系对应了起来.本文就参考了该文并结合矩阵的相关知识把SVD

机器学习基础篇——矩阵特征值分解含义解析及应用

特征值与特征向量的几何意义: 矩阵的乘法是什么,别只告诉我只是"前一个矩阵的行乘以后一个矩阵的列",还会一点的可能还会说"前一个矩阵的列数等于后一个矩阵的行数才能相乘",然而,这里却会和你说--那都是表象. 矩阵乘法真正的含义是变换,我们学<线性代数>一开始就学行变换列变换,矩阵乘法就是线性变换,若以其中一个向量A为中心,则B的作用主要是使A发生如下变化: 伸缩 clf;     %用来清除图形的命令 A = [0, 1, 1, 0, 0;... 1, 

矩阵特征值分解与奇异值分解含义解析及应用

此文有一半转载自他出,主要在这进行个整理,具体内容文中都有相关的转载链接. 特征值与特征向量的几何意义 矩阵的乘法是什么,别只告诉我只是"前一个矩阵的行乘以后一个矩阵的列",还会一点的可能还会说"前一个矩阵的列数等于后一个矩阵的行数才能相乘",然而,这里却会和你说--那都是表象. 矩阵乘法真正的含义是变换,我们学<线性代数>一开始就学行变换列变换,那才是线代的核心--别会了点猫腻就忘了本--对,矩阵乘法 就是线性变换,若以其中一个向量A为中心,则B的作用

讲一下numpy的矩阵特征值分解

主要还是调包: from numpy.linalg import eig 特征值分解:  A = P*B*PT  当然也可以写成 A = PT*B*P  其中B为对角元为A的特征值的对角矩阵. 首先A得正定,然后才能在实数域上分解, >>> A = np.random.randint(-10,10,(4,4)) >>> A array([[ 6, 9, -10, -1], [ 5, 9, 5, -5], [ -8, 7, -4, 4], [ -1, -9, 0, 6]]

利用QR算法求解矩阵的特征值和特征向量

利用QR算法求解矩阵的特征值和特征向量 为了求解一般矩阵(不是那种幼稚到shi的2 x 2矩阵)的特征值. 根据定义的话,很可能需要求解高阶方程... 这明显是个坑...高阶方程你肿么破... 折腾了好久 1.我要求特征值和特征向量. 2.找到一种算法QR分解矩阵求解特征值 3.QR矩阵分解需要Gram-schimidt正交化分解 有一种很明显的感觉,往往在现在很难有 很系统 很深入 的学习某一个学科的某一门知识. 往往学的时候"靠,学这东西有什么用""学了这么久,也不知道怎么用,不想学" 到后

特征值分解,奇异值分解(SVD)

特征值分解和奇异值分解在机器学习领域都是属于满地可见的方法.两者有着很紧密的关系,我在接下来会谈到,特征值分解和奇异值分解的目的都是一样,就是提取出一个矩阵最重要的特征. 1. 特征值: 如果说一个向量v是方阵A的特征向量,将一定可以表示成下面的形式: 写成矩阵形式: 这时候λ就被称为特征向量v对应的特征值,一个矩阵的一组特征向量是一组正交向量. 2. 特征分解: 特征值分解是将一个矩阵分解成下面的形式: 其中Q是这个矩阵A的特征向量组成的矩阵,正交矩阵是可逆的.Σ?=?diag(λ1,?λ2,

特征值分解和SVD

特征值分解 如果说一个向量v是方阵A的特征向量,将一定可以表示成下面的形式: 这时候λ就被称为特征向量v对应的特征值,一个矩阵的一组特征向量是一组正交向量.特征值分解是将一个矩阵分解成下面的形式: 其中Q是这个矩阵A的特征向量组成的矩阵,Σ是一个对角阵,每一个对角线上的元素就是一个特征值.我这里引用了一些参考文献中的内容来说明一下.首先,要明确的是,一个矩阵其实就是一个线性变换,因为一个矩阵乘以一个向量后得到的向量,其实就相当于将这个向量进行了线性变换.比如说下面的一个矩阵: 它其实对应的线性变