传送门
解析:
显然可以用
M
a
t
r
i
x
−
T
r
e
e
Matrix-Tree
Matrix−Tree来做 推导。
思路:
我们直接建出基尔霍夫矩阵
H
H
H,显然我们可以把它分成四块:
左上角为
A
A
A是一个
n
×
n
n\times n
n×n的对角线为
m
m
m的矩阵,其余为0。
右上角为
B
B
B是一个
n
×
(
m
−
1
)
n\times (m-1)
n×(m−1)的全部为
−
1
-1
−1的矩阵
左下角为
C
C
C是一个
(
m
−
1
)
×
n
(m-1)\times n
(m−1)×n的全部为
−
1
-1
−1的矩阵,即矩阵
B
B
B的转置
右下角为
D
D
D是一个
(
m
−
1
)
×
(
m
−
1
)
(m-1)\times (m-1)
(m−1)×(m−1)的对角线为
n
n
n的矩阵,其余为0。
把矩阵推导一下: ∣ H ∣ = ∣ A ∣ × ∣ D − C × A − 1 × B ∣ |H|=|A|\times |D-C\times A^{-1}\times B| ∣H∣=∣A∣×∣D−C×A−1×B∣
那么 ∣ A ∣ |A| ∣A∣就显然是 n m n^m nm。
后面的再推一下。
A − 1 A^{-1} A−1是 A A A的逆,规模相同,对角线为 1 / m 1/m 1/m。
那么这一坨就可以推出了: C × A − 1 × B C\times A^{-1}\times B C×A−1×B是一个规模为 ( m − 1 ) × ( m − 1 ) (m-1)\times(m-1) (m−1)×(m−1),所有元素为 n / m n/m n/m的矩阵。
后面一大坨就直接作差得到一个矩阵 T T T, T T T的对角线上全部是 n − n / m n-n/m n−n/m,其余部分是 − n / m -n/m −n/m,规模为 ( m − 1 ) × ( m − 1 ) (m-1)\times (m-1) (m−1)×(m−1)。
我们直接把 n / m n/m n/m提出来得到新的矩阵 T ′ T' T′, T ′ T' T′的对角线就全部都是 m − 1 m-1 m−1,其余部分全部都是 − 1 -1 −1。
这个 T ′ T' T′。。。
好的这道题做完了。
这个 T ′ T' T′对应的基尔霍夫矩阵求的就是有 m m m个节点的无向完全图的生成树个数 。由 p r u f e r prufer prufer序列瞎推一波可以知道生成树个数就是 m m − 2 m^{m-2} mm−2
再把刚才提出来的 ( n / m ) m − 1 (n/m)^{m-1} (n/m)m−1和原来的 ∣ A ∣ |A| ∣A∣乘回去就可以知道我们要求的东西了 K n , m = ∣ H n , m ∣ = n m − 1 × m n − 1 K_{n,m}=|H_{n,m}|=n^{m-1}\times m^{n-1} Kn,m=∣Hn,m∣=nm−1×mn−1
trick:
直接乘肯定会爆
l
o
n
g
l
o
n
g
long long
longlong,考场上又不可能用__int128。
所以去学习一下龟速乘吧。
当然还有 O ( 1 ) O(1) O(1)的龟速乘。
代码:
#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;
}