[BZOJ4766]文艺计算姬
试题描述
"奋战三星期,造台计算机"。小W响应号召,花了三星期造了台文艺计算姬。文艺计算姬比普通计算机有更多的艺术细胞。普通计算机能计算一个带标号完全图的生成树个数,而文艺计算姬能计算一个带标号完全二分图的生成树个数。更具体地,给定一个一边点数为n,另一边点数为m,共有n*m条边的带标号完全二分图K_{n,m},计算姬能快速算出其生成树个数。小W不知道计算姬算的对不对,你能帮助他吗?
输入
仅一行三个整数n,m,p,表示给出的完全二分图K_{n,m}
1 <= n,m,p <= 10^18
输出
仅一行一个整数,表示完全二分图K_{n,m}的生成树个数,答案需要模p。
输入示例
2 3 7
输出示例
5
数据规模及约定
见“输入”
题解
矩阵树定理,当科普一下吧。。。
构造出基尔霍夫矩阵的主子式,然后算行列式打表找规律。
答案是 nm-1 · mn-1,我并不会证。。。。。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cmath>
using namespace std;
#define LL long long
LL read() {
LL x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
return x * f;
}
LL n, m, p;
LL Mul(LL a, LL b) {
LL ans = 0, t = a;
while(b) {
if(b & 1) (ans += t) %= p;
(t += t) %= p; b >>= 1;
}
return ans;
}
LL Pow(LL a, LL b) {
LL ans = 1, t = a;
while(b) {
if(b & 1) ans = Mul(ans, t);
t = Mul(t, t); b >>= 1;
}
return ans;
}
int main() {
n = read(); m = read(); p = read();
printf("%lld\n", Mul(Pow(n, m - 1), Pow(m, n - 1)));
return 0;
}
读入开 long long,然后需要“快速乘”。