置换矩阵

news/2024/11/29 10:57:09/

置换矩阵

在这里插入图片描述

题解

首先对于有大于1个环的情况,明显行列式值是为零的。
因为这种情况必定有一个环的长度小于 ∣ n 2 ∣ \left|\frac{n}{2}\right| 2n,所以就一定可以将一个环的区域全部消成0,这样答案就肯定为0了。

那么对于 p 1 = n , p i = i − 1 p_{1}=n,p_{i}=i-1 p1=n,pi=i1的部分呢,我可以很容易看出这是一个循环行列式。
对于循环行列式的值,我们有着一种特别的求法。
d e t ( A ) = ∏ i = 0 i − 1 ( ∑ j = 0 n − 1 a j ω i j ) det(A)=\prod_{i=0}^{i-1}(\sum_{j=0}^{n-1}a_j\omega^{ij}) det(A)=i=0i1(j=0n1ajωij)
f ( x ) = ∑ j = 0 n − 1 a j x j f(x)=\sum_{j=0}^{n-1}a_jx^{j} f(x)=j=0n1ajxj,那么有
d e t ( A ) = ∏ i = 0 i − 1 f ( ω i ) det(A)=\prod_{i=0}^{i-1}f(\omega^i) det(A)=i=0i1f(ωi)
其中 ω \omega ω表示单位根

证明
考虑范蒙德矩阵,
在这里插入图片描述
其中 ω n \omega_n ωn表示 n n n次单位根,即 ω n = e 2 π n \omega_{n}=e^{\frac{2\pi}{n}} ωn=en2π
将范德蒙矩阵与 n n n阶循环行列式相乘,由于 ω n n + k = ω n k \omega_n^{n+k}=\omega_n^k ωnn+k=ωnk,有
在这里插入图片描述
两边取行列式,则有
d e t ( A ) d e t ( V ) = ( ∏ i = 0 n − 1 f ( ω n j ) ) d e t ( V ) det(A)det(V)=(\prod_{i=0}^{n-1}f(\omega_n^j))det(V) det(A)det(V)=(i=0n1f(ωnj))det(V)
考虑到 d e t ( V ) = ∏ 0 ⩽ j < i < n ( ω n i − ω n j ) det(V)=\prod_{0\leqslant j<i<n}(\omega_n^i-\omega_n^j) det(V)=0j<i<n(ωniωnj)
w n 0 , w n 1 , . . . w n n − 1 w_n^0,w_n^1,...w_n^{n-1} wn0,wn1,...wnn1互不相等,故 d e t ( V ) ≠ 0 det(V)\not = 0 det(V)=0,有
d e t ( A ) = ∏ i = 0 i − 1 f ( ω i ) det(A)=\prod_{i=0}^{i-1}f(\omega^i) det(A)=i=0i1f(ωi)
证毕

但我们在模的意义下有如何计算呢?
考虑到 ω 0 , ω 1 , . . . , ω n − 1 \omega^0,\omega^1,...,\omega^{n-1} ω0,ω1,...,ωn1 B ( x ) = x n − 1 B(x)=x^n-1 B(x)=xn1的所有根,我们可以通过这东西来进行计算。
λ 1 , λ n \lambda_1,\lambda_n λ1,λn n n n次多项式 A ( x ) = f ( x ) A(x)=f(x) A(x)=f(x)的所有根, μ 1 , . . . , μ m \mu_1,...,\mu_m μ1,...,μm m m m次多项式 B ( x ) B(x) B(x)的所有根,
定义函数 F ( A , B ) = b m n ∏ i = 1 m A ( μ i ) F(A,B)=b_m^n\prod_{i=1}^{m}A(\mu_i) F(AB)=bmni=1mA(μi),显然 F ( A , B ) F(A,B) F(A,B)就是我们要求的答案
显然有
F ( A , B ) = b m n ∏ i = 1 n A ( μ i ) = a n m b m n ∏ ( μ i − λ j ) = ( − 1 ) n m a n m ∏ i = 1 n B ( λ i ) F(A,B)=b_m^n\prod_{i=1}^{n}A(\mu_i)=a_n^mb_m^n\prod(\mu_i-\lambda_j)=(-1)^{nm}a_n^m\prod_{i=1}^{n}B(\lambda_i) F(A,B)=bmni=1nA(μi)=anmbmn(μiλj)=(1)nmanmi=1nB(λi)
结合定义,可以得到以下性质

  • F ( A , B ) = ( − 1 ) n m F ( B , A ) F(A,B)=(-1)^{nm}F(B,A) F(A,B)=(1)nmF(B,A)
  • F ( A , B ) = a n m b m n ( n = 0 ∨ m = 0 ) F(A,B)=a_n^mb_m^n(n=0\lor m=0) F(A,B)=anmbmn(n=0m=0)
  • F ( A − C B , B ) = F ( A , B ) ( b m = 1 ) F(A-CB,B)=F(A,B)(b_m=1) F(ACB,B)=F(A,B)(bm=1)
  • F ( A , B ) = ( − 1 ) d e g ( A ) − d e g ( A − C B ) F ( A − C B , B ) F(A,B)=(-1)^{deg(A)-deg(A-CB)}F(A-CB,B) F(A,B)=(1)deg(A)deg(ACB)F(ACB,B)

于是此时我们就可以 O ( n 2 ) O(n^2) O(n2)地计算出这样行列式的值了。

但对于不是循环行列式的行列式呢?
我们发现我们对于原循环求出的行列式可以通过对某些列的交换达到来改变原序列,从而使它成为循环行列式。
我们接着就可以发现交换次数只会改变的行列式的正负,而交换次数又是等于点一的路径的序列的逆序对数的。
所以我们只需要做完子任务3后求一下逆序对数,将答案改变一下正负就能够完成subtask4了。

总时间复杂度还是 O ( n 2 ) O\left(n^2\right) O(n2)

源码

一个正负判断了一个下午。。。

#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define MAXN 5005
#define lowbit(x) (x&-x)
#define reg register
typedef long long LL;
typedef unsigned long long uLL;
typedef unsigned int uint;
typedef pair<int,int> pii;
const int INF=0x7f7f7f7f;
const int mo=1e9+7;
const double PI=acos(-1.0);
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
int n,m,a[MAXN],p[MAXN],q[MAXN],A[MAXN],B[MAXN],pp[MAXN];
int add(int x,int y){return x+y<mo?x+y:x+y-mo;}
int qkpow(int a,int s){int t=1;while(s){if(s&1)t=1ll*a*t%mo;a=1ll*a*a%mo;s>>=1;}return t;}
signed main(){freopen("matrix.in","r",stdin);freopen("matrix.out","w",stdout);read(n);m=n;int ans=1,now=1,tmp=0,sum=0;for(int i=1;i<=n;i++)read(a[i]);for(int i=1;i<=n;i++)read(p[i]),q[p[i]]=i;pp[1]=1;now=q[1];tmp++;while(now^1)pp[tmp+1]=now,now=q[now],tmp++;if(tmp<n){puts("0");return 0;}for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++)if(pp[i]>pp[j])sum++;for(int i=0;i<n;i++)A[i]=a[pp[i+1]];B[0]=mo-1;B[m]=1;n--;ans=1;while(1){if(n<m)swap(A,B),ans=(n&m)&1?mo-ans:ans,swap(n,m);if(!m){ans=1ll*ans*qkpow(B[0],n)%mo;break;}const int d=1ll*A[n]*qkpow(B[m],mo-2)%mo;for(int i=m;i>=0;i--)A[n-m+i]=add(A[n-m+i],mo-1ll*d*B[i]%mo);int L=0;while(n&&!A[n])n--,L++;ans=1ll*ans*qkpow(B[m],L)%mo;}printf("%d\n",(sum&1)?add(mo,-ans):ans);return 0;
}

谢谢!!!


http://www.ppmy.cn/news/660590.html

相关文章

置换贴图(Displacement map),凹凸贴图(Bump map)与法线贴图(Normal map)的区别

英文原文地址《Difference between Displacement , Bump and Normap Maps》 By Pluralsight on August 14, 2014 你是否在学习如何为你的3D素材制作贴图的时候遇到了点小挫折&#xff1f;不要灰心&#xff01;很多贴图或3D领域的艺术家在初次遇到凹凸贴图(Bump map)&#xff0c…

《操作系统》by李治军 | 实验9 - proc文件系统的实现

目录 一、实验目的 二、实验内容 三、实验准备 1. procfs 简介 2. 基本思路 四、实验过程 1. 增加新的文件类型 2. 让 mknod() 支持新的文件类型 &#xff08;1&#xff09;修改 mknod 系统调用 &#xff08;2&#xff09;初始化 procfs 3. 让 proc 文件可读 &…

Learn Mongodb 可是工具及基本命令的使用 ③

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; PHP MYSQL &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f44…

英雄联盟之盖伦

出门装备&#xff1a;鞋子、血瓶&#xff1b;中期装备&#xff1a;水银之靴、日炎斗篷&#xff1b;后期装备&#xff1a;顺风时&#xff1a;幽梦之灵、兰顿之兆、大冰锤、自然之力&#xff1b;逆风时&#xff1a;狂徒铠甲、女妖面纱、守护天使 技能分析&#xff1a;Q&#xff…

HTML5-实现英雄联盟官网《电竞小说》和《在线客服》页面

目录---- 电竞小说...........1在线客服...........2 1.电竞小说 2.在线客服 进入主页查看资源&#xff0c;包括代码段和实验报告哦。

【新星计划】技术博客写作技巧经验分享

序言 写技术博客需要一定的专业知识和写作技巧&#xff0c;它是一个很好的方式来分享你的经验和知识&#xff0c;同时也是一个展示你的专业能力和建立自己品牌的机会。 以下是一些准备和建议&#xff0c;希望可以帮助你写出有用和有吸引力的技术博客&#xff1a; 写在前面 我报…

Springboot集成mybatisplus的问题处理

文章目录 前言一个接口多个实现解决方案 Invalid bound statement (not found)解决方案 总结 前言 新接触mybatisPlus的小伙伴可能会遇到各种各样的问题&#xff0c;尤其是mybatis的xml文件及类的注入问题&#xff0c;下面我们就看一下常见的问题吧。 一个接口多个实现 报错…

css 水珠动图,使用CSS3实现的水滴涟漪动画

CSS 语言&#xff1a; CSSSCSS 确定 body { background-color: #31C5F3; overflow: hidden; } div { margin: 175px auto; } .wave { position: relative; opacity: 0; top: 0; width: 2px; height: 0.5px; border: #FFF 5px solid; border-radius: 300px / 75px; -webkit-anim…