1. 程式人生 > >[BZOJ4766]文藝計算姬(矩陣+矩陣樹定理+快速加)

[BZOJ4766]文藝計算姬(矩陣+矩陣樹定理+快速加)

題目:

我是超連結

題解:

完全二分圖:X中的任一頂點與Y中每一個頂點均有且僅有唯一的一條邊相連
不難發現K矩陣是長這個樣子的
這裡寫圖片描述
我們對這個矩陣分一下塊,左上角是n * n的對角線為m的矩陣A,右上角是全為-1的n * (m-1)的矩陣B,左下角是全為-1的(m-1) * n的矩陣C,右下角是對角線為n的(m-1)*(m-1)的矩陣設為D

分塊矩陣的行列式求法:
 
A 0
0 B
行列式為|A||B|
 
0 A
B 0
行列式為(-1)^(mn)|A||B|
 
A B
C D
行列式為|A||D-C*A^(-1)*B|

這個矩陣的|A|顯然是m^n
後面A1為A的逆矩陣,是一個主對角線為1/m,其餘值為0的矩陣

逆矩陣:A的逆矩陣為與A相乘得單位矩陣的矩陣
單位矩陣:主對角線為1,其餘為0的矩陣
可逆矩陣:有逆矩陣的矩陣,可以通過|A|!=0判斷

可以發現後面的矩陣為這裡寫圖片描述
即主對角線為n-n/m,其餘為-n/m的矩陣

這裡寫圖片描述
然而打表找規律才是這道題目的正確開啟方式

這道題目需要用快速乘,而且快速冪的時候也要快速乘,不然GG

題解中部分圖片引自dalao,侵刪

程式碼:

#include <cstdio>
#define LL long long 
using namespace std;
LL n,m
,p; LL ksc(LL a,LL k) { LL ans=0; for (;k;k>>=1,a=2ll*a%p) if (k&1) ans=(ans+a)%p; return ans; } LL ksm(LL a,LL k) { LL ans=1; a%=p; for (;k;k>>=1,a=ksc(a,a)) if (k&1) ans=ksc(ans,a); return ans; } int main() { scanf("%lld%lld%lld",&n,&m
,&p); printf("%lld",ksc(ksm(n,m-1),ksm(m,n-1))); }