版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/83065303
传送门
解析:
显然可以用
来做 推导。
思路:
我们直接建出基尔霍夫矩阵
,显然我们可以把它分成四块:
左上角为
是一个
的对角线为
的矩阵,其余为0。
右上角为
是一个
的全部为
的矩阵
左下角为
是一个
的全部为
的矩阵,即矩阵
的转置
右下角为
是一个
的对角线为
的矩阵,其余为0。
把矩阵推导一下:
那么 就显然是 。
后面的再推一下。
是 的逆,规模相同,对角线为 。
那么这一坨就可以推出了: 是一个规模为 ,所有元素为 的矩阵。
后面一大坨就直接作差得到一个矩阵 , 的对角线上全部是 ,其余部分是 ,规模为 。
我们直接把 提出来得到新的矩阵 , 的对角线就全部都是 ,其余部分全部都是 。
这个 。。。
好的这道题做完了。
这个 对应的基尔霍夫矩阵求的就是有 个节点的无向完全图的生成树个数 。由 序列瞎推一波可以知道生成树个数就是
再把刚才提出来的 和原来的 乘回去就可以知道我们要求的东西了
trick:
直接乘肯定会爆
,考场上又不可能用__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;
}