1. 程式人生 > >2018.10.15【BZOJ4766】文藝計算姬(矩陣快速冪)(矩陣樹)(prufer序列)(結論題)

2018.10.15【BZOJ4766】文藝計算姬(矩陣快速冪)(矩陣樹)(prufer序列)(結論題)

傳送門

解析:

顯然可以用MatrixTreeMatrix-Tree來做 推導。

思路:

我們直接建出基爾霍夫矩陣HH,顯然我們可以把它分成四塊:
左上角為AA是一個n×nn\times n的對角線為mm的矩陣,其餘為0。
右上角為BB是一個n×(m1)n\times (m-1)的全部為1-1的矩陣
左下角為CC是一個(m1)×n(m-1)\times n的全部為1-1的矩陣,即矩陣BB的轉置
右下角為DD是一個(m1)×(m1)(m-1)\times (m-1)的對角線為nn的矩陣,其餘為0。

把矩陣推導一下:H=A×DC×A1×B|H|=|A|\times |D-C\times A^{-1}\times B|

那麼A|A|就顯然是nmn^m

後面的再推一下。

A1A^{-1}AA的逆,規模相同,對角線為1/m1/m

那麼這一坨就可以推出了:C×A1×BC\times A^{-1}\times B是一個規模為(m1)×(m1)(m-1)\times(m-1),所有元素為n/mn/m的矩陣。

後面一大坨就直接作差得到一個矩陣TTTT的對角線上全部是nn

/mn-n/m,其餘部分是n/m-n/m,規模為(m1)×(m1)(m-1)\times (m-1)

我們直接把n/mn/m提出來得到新的矩陣TT'TT'的對角線就全部都是m1m-1,其餘部分全部都是1-1

這個TT'。。。

好的這道題做完了。

這個TT'對應的基爾霍夫矩陣求的就是有 mm個節點的無向完全圖的生成樹個數 。由pruferprufer序列瞎推一波可以知道生成樹個數就是mm2m^{m-2}

再把剛才提出來的(n

/m)m1(n/m)^{m-1}和原來的A|A|乘回去就可以知道我們要求的東西了Kn,m=Hn,m=nm1×mn1K_{n,m}=|H_{n,m}|=n^{m-1}\times m^{n-1}

trick:

直接乘肯定會爆longlonglong long,考場上又不可能用__int128。
所以去學習一下龜速乘吧。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const

inline ll getint(){
	re ll num;
	re char c;
	while(!isdigit(c=gc()));num=c^48;
	while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
	return num;
}

ll mod;

inline ll mul(ll a,ll b){
	return (a*b-(ll)((long double)a/mod*b)*mod+mod)%mod;
/*	ll ans=0;
	while(b){
		if(b&1)ans=(ans+a)%mod;
		a=(a+a)%mod;
		b>>=1;
	}
	return ans;*/
}

inline ll quickpow(ll a,ll b){
	ll ans=1;
	while(b){
		if(b&1)ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

ll n,m;
signed main(){
	n=getint(),m=getint(),mod=getint();
	cout<<(ll)mul(quickpow(n,m-1),quickpow(m,n-1));
	return 0;
}