zoukankan      html  css  js  c++  java
  • 矩阵特征多项式的求法

    就这个东西看了好久才看懂,我在想啥啊

    结论:相似矩阵的特征多项式相同

    证明:代入定义式即可。

    (A)(B) 相似也就是存在可逆矩阵 (P) 使得 (A=P^{-1}BP)

    只要在对 (A) 做初等行变换的时候,同时左乘上它的逆,就可以维持相似性。具体实现背代码

    然后就可以得到一个 Hessenberg 矩阵,也就是 (ige j+2)(a_{i,j}=0)。设 (f_m) 表示规模为 (m) 的顺序主子式的特征多项式,则有

    [f_k=(x-a_{k,k})f_{k-1}-a_{k,k-1}a_{k-1,k}f_{k-2}-a_{k,k-1}a_{k-1,k-2}a_{k-2,k}f_{k-3}-cdots ]

    直接递推求即可。两部分的时间复杂度均为 (O(n^3))

    // Gym102984K
    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N = 503, mod = 998244353;
    template<typename T>
    void read(T &x){
    	int ch = getchar(); x = 0;
    	for(;ch < '0' || ch > '9';ch = getchar());
    	for(;ch >= '0' && ch <= '9';ch = getchar()) x = x * 10 + ch - '0';
    }
    int n, q, x, a[N][N], p[N][N];
    int ksm(int a, int b){
    	int res = 1;
    	for(;b;b >>= 1, a = (LL)a * a % mod)
    		if(b & 1) res = (LL)res * a % mod;
    	return res;
    } void qmo(int &x){x += x >> 31 & mod;}
    int main(){
    	read(n); read(q);
    	for(int i = 1;i <= n;++ i)
    		for(int j = 1;j <= n;++ j)
    			read(a[i][j]);
    	for(int i = 1;i < n-1;++ i){
    		if(!a[i+1][i])
    			for(int j = i+2;j <= n;++ j) if(a[j][i]){
    				for(int k = 1;k <= n;++ k) swap(a[i+1][k], a[j][k]);
    				for(int k = 1;k <= n;++ k) swap(a[k][i+1], a[k][j]);
    				break;
    			}
    		if(!a[i+1][i]) continue;
    		int inv = ksm(a[i+1][i], mod-2);
    		for(int j = i+2;j <= n;++ j) if(a[j][i]){
    			int tmp = (LL)a[j][i] * inv % mod;
    			for(int k = i;k <= n;++ k) qmo(a[j][k] -= (LL)tmp * a[i+1][k] % mod);
    			for(int k = 1;k <= n;++ k) a[k][i+1] = (a[k][i+1] + (LL)tmp * a[k][j]) % mod;
    		}
    	} p[0][0] = 1;
    	for(int k = 1;k <= n;++ k){
    		for(int i = 1;i <= k;++ i) p[k][i] = p[k-1][i-1];
    		for(int i = 0;i <= k;++ i) qmo(p[k][i] -= (LL)a[k][k] * p[k-1][i] % mod);
    		int now = 1, tmp;
    		for(int i = k-1;i;-- i){
    			now = (LL)now * a[i+1][i] % mod;
    			tmp = (mod - (LL)now) * a[i][k] % mod;
    			for(int j = 0;j <= i;++ j) p[k][j] = (p[k][j] + (LL)tmp * p[i-1][j]) % mod;
    		}
    	} while(q --){
    		read(x); int ans = 0;
    		for(int i = n;~i;-- i) ans = ((LL)ans * x + p[n][i]) % mod;
    		if(ans && (n & 1)) ans = mod - ans; printf("%d ", ans);
    	}
    }
    

    SZOJ2651【模板】???

    给定两个简单无向图 (G_1,G_2) 和正整数 (p),求 (G_1square G_2) 的生成树个数模 (p) 的值。其中 (square) 表示无向图的笛卡尔积

    (n,mle 500)(10^9+7le ple 10^9+181)(p) 为质数。

    解法懒得写了,自己看着办(

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    const int N = 503;
    int mod, a[N][N], p[N][N]; char str[N];
    int ksm(int a, int b){
    	int res = 1;
    	for(;b;b >>= 1, a = (LL)a * a % mod)
    		if(b & 1) res = (LL)res * a % mod;
    	return res;
    } void qmo(int &x){x += x >> 31 & mod;}
    void work(int n, VI &v){
    	memset(a, 0, sizeof a); memset(p, 0, sizeof p);
    	for(int i = 1;i < n;++ i){
    		scanf("%s", str+1);
    		for(int j = i+1;j <= n;++ j)
    			if(str[j-i] == '1'){
    				++a[i][i]; ++a[j][j];
    				a[i][j] = a[j][i] = mod-1;
    			}
    	}
    	for(int i = 1;i < n-1;++ i){
    		if(!a[i+1][i])
    			for(int j = i+2;j <= n;++ j) if(a[j][i]){
    				for(int k = 1;k <= n;++ k) swap(a[i+1][k], a[j][k]);
    				for(int k = 1;k <= n;++ k) swap(a[k][i+1], a[k][j]);
    				break;
    			}
    		if(!a[i+1][i]) continue;
    		int inv = ksm(a[i+1][i], mod-2);
    		for(int j = i+2;j <= n;++ j) if(a[j][i]){
    			int tmp = (LL)a[j][i] * inv % mod;
    			for(int k = i;k <= n;++ k) qmo(a[j][k] -= (LL)tmp * a[i+1][k] % mod);
    			for(int k = 1;k <= n;++ k) a[k][i+1] = (a[k][i+1] + (LL)tmp * a[k][j]) % mod;
    		}
    	} p[0][0] = 1;
    	for(int k = 1;k <= n;++ k){
    		for(int i = 1;i <= k;++ i) p[k][i] = p[k-1][i-1];
    		for(int i = 0;i <= k;++ i) qmo(p[k][i] -= (LL)a[k][k] * p[k-1][i] % mod);
    		int now = 1, tmp;
    		for(int i = k-1;i;-- i){
    			now = (LL)now * a[i+1][i] % mod;
    			tmp = (mod - (LL)now) * a[i][k] % mod;
    			for(int j = 0;j <= i;++ j) p[k][j] = (p[k][j] + (LL)tmp * p[i-1][j]) % mod;
    		}
    	} v.resize(n+1);
    	for(int i = 0;i <= n;++ i) v[i] = p[n][i];
    }
    VI modu(VI a, const VI &b){
    	int n = a.size() - 1, m = b.size() - 1, tmp = ksm(b[m], mod-2);
    	while(n >= m){
    		int x = (LL)tmp * a[n] % mod;
    		for(int j = 0;j < m;++ j) qmo(a[n-m+j] -= (LL)x * b[j] % mod);
    		a.pop_back(); while(!a.empty() && !a.back()) a.pop_back();
    		n = a.size() - 1;
    	} return a;
    }
    int result(const VI &a, const VI &b){
    	if(b.empty()) return 0;
    	if(b.size() == 1) return ksm(b[0], a.size() - 1);
    	VI c = modu(a, b);
    	int ans = (LL)ksm(b.back(), a.size() - c.size()) * result(b, c) % mod;
    	if(ans && !((a.size() & 1) || (b.size() & 1))) ans = mod - ans;
    	return ans;
    }
    int n, m, ans; VI v1, v2;
    int main(){
    	scanf("%d%d%d", &n, &m, &mod);
    	work(n, v1); work(m, v2); v1.erase(v1.begin());
    	for(int i = 1;i <= m;i += 2) if(v2[i]) v2[i] = mod - v2[i];
    	if(n <= m){
    		ans = (LL)result(v2, v1) * v2[1] % mod;
    		if(ans && (n & 1) && (m & 1)) ans = mod - ans;
    	} else {
    		ans = (LL)result(v1, v2) * v2[1] % mod;
    		if(ans && (m & 1)) ans = mod - ans;
    	} printf("%d", ans);
    }
    
  • 相关阅读:
    从简单需求到OLAP的RANK系列函数
    数据库的Index Scan V.S. Rscan
    z/OS上Dataset 的移动
    如何保存CONSOLE LOG
    c#对文件进行MD5加密校验
    基于webpivottable做的透视表
    通过asp.net程序来控制自己开发的windows服务
    AES加密和解密
    C#添加日志
    cmd执行mssql脚本或者执行mysql脚本
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/14665374.html
Copyright © 2011-2022 走看看