题目地址
描述
给定一个带标号完全二分图 Kn,m,计算其生成树个数。
分析
答案为:
nm−1mn−1证明:根据 Matrix-Tree 定理,Kn,m 的生成树数量等于其基尔霍夫矩阵去掉一行一列所得行列式的绝对值。
∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣m0⋮0−1−1⋮−10m⋮0−1−1⋮−1⋯⋯⋱⋯⋯⋯⋱⋯00⋮m−1−1⋮−1−1−1⋮−1n0⋮0−1−1⋮−10n⋮0⋯⋯⋱⋯⋯⋯⋱⋯−1−1⋮−100⋮n∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣注意上面有 n 行,而下面只有 m−1 行(我们去掉了一行一列)。我们用前 n 行来消去左下角的 −1:
∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣m0⋮000⋮00m⋮000⋮0⋯⋯⋱⋯⋯⋯⋱⋯00⋮m00⋮0−1−1⋮−1n−mn−mn⋮−mn−1−1⋮−1−mnn−mn⋮−mn⋯⋯⋱⋯⋯⋯⋱⋯−1−1⋮−1−mn−mn⋮n−mn∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣∣设
D1=∣∣∣∣∣∣∣∣m0⋮00m⋮0⋯⋯⋱⋯00⋮m∣∣∣∣∣∣∣∣,D2=∣∣∣∣∣∣∣∣∣∣∣n−mn−mn⋮−mn−mnn−mn⋮−mn⋯⋯⋱⋯−mn−mn⋮n−mn∣∣∣∣∣∣∣∣∣∣∣由于右下角都是 0,此时行列式的值转化为 D1D2。
显然 D1=nm,我们考虑 D2:
∣∣∣∣∣∣∣∣∣∣∣n−mn−mn⋮−mn−mnn−mn⋮−mn⋯⋯⋱⋯−mn−mn⋮n−mn∣∣∣∣∣∣∣∣∣∣∣从第二行开始,每一行都加到第一行:
D2=∣∣∣∣∣∣∣∣∣∣∣n−(m−1)mn−mn⋮−mnn−(m−1)mnn−mn⋮−mn⋯⋯⋱⋯n−(m−1)mn−mn⋮n−mn∣∣∣∣∣∣∣∣∣∣∣可提出常数:
D2=(n−(m−1)mn)∣∣∣∣∣∣∣∣∣∣1−mn⋮−mn1n−mn⋮−mn⋯⋯⋱⋯1−mn⋮n−mn∣∣∣∣∣∣∣∣∣∣将第一行乘 mn 加到下面每一行:
D2=(n−(m−1)mn)∣∣∣∣∣∣∣∣10⋮01n⋮0⋯⋯⋱⋯10⋮n∣∣∣∣∣∣∣∣=(n−(m−1)mn)⋅nm−2=mn⋅nm−2化简得:
D2=mnm−1所以:
D1D2=mnmnm−1=nm−1mn−1即得证。
代码
// Created by Sengxian on 2017/3/20.
// Copyright (c) 2017年 Sengxian. All rights reserved.
// BZOJ 4766 Matrix-Tree + 行列式化简
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n, m, mod;
inline ll modMul(ll a, ll b) {
ll res = 0;
while (b) {
if (b & 1) (res += a) %= mod;
(a <<= 1) %= mod;
b >>= 1;
}
return res;
}
inline ll modPow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = modMul(res, a);
a = modMul(a, a);
b >>= 1;
}
return res;
}
int main() {
scanf("%lld%lld%lld", &n, &m, &mod);
printf("%lld\n", modMul(modPow(n, m - 1), modPow(m, n - 1)));
return 0;
}