题面传送门
一道代码让你觉得它是道给初学者做的题,然鹅我竟没想到?
首先考虑做一步转化,我们考虑将整棵树按深度奇偶性转化为一张二分图,即将深度为奇数的点视作二分图的左部,深度为偶数的点视作二分图的右部,这样我们肯定只能在左右部点之间连边,这大概算得上一个小套路吧,不过这还是萌新第一次见到这个套路呢,大佬不喜勿喷(
接下来考虑怎么求方案数,显然 \(1\) 只能放在左部点,我们还需从另外 \(n-1\) 个点中选出 \(k-1\) 个扔给左部,方案数为 \(\dbinom{n-1}{k-1}\),我们不妨就假设这 \(k-1\) 个点为 \([2,k]\cap\mathbb{Z}\),于是现在问题转化为:有一张二分图,左部有 \(k\) 个点,右部有 \(n-k\) 个点,要在它们之间连 \(n-1\) 条边使其构成一棵生成树。
看到这个问法我们很自然地想到矩阵树定理,不过此题 \(n\) 数据范围很大,矩阵树定理显然会炸,网上某篇题解给出了一个 prufer 序列的做法,然鹅我没看懂。注意到这张图很特殊,因此考虑手推行列式。首先很明显这张图的基尔霍夫矩阵如下:
\[\begin{bmatrix}
n-k&0&0&\cdots&0&-1&-1&\cdots&-1\\
0&n-k&0&\cdots&0&-1&-1&\cdots&-1\\
0&0&n-k&\cdots&0&-1&-1&\cdots&-1\\
\vdots&\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&0&\cdots&n-k&-1&-1&\cdots&-1\\
-1&-1&-1&\cdots&-1&k&0&\cdots&0\\
-1&-1&-1&\cdots&-1&0&k&\cdots&0\\
\vdots&\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots\\
-1&-1&-1&\cdots&-1&0&0&\cdots&k\\
\end{bmatrix}
\]
其中左边有 \(k\) 列,右边有 \(n-k\) 列。
去掉第一行第一列后的矩阵长这样:
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&\cdots&-1\\
0&n-k&\cdots&0&-1&-1&\cdots&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&\cdots&-1\\
-1&-1&\cdots&-1&k&0&\cdots&0\\
-1&-1&\cdots&-1&0&k&\cdots&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots\\
-1&-1&\cdots&-1&0&0&\cdots&k\\
\end{bmatrix}
\]
其中左边有 \(k-1\) 列,右边有 \(n-k\) 列。
接下来考虑求行列式,考虑使用倍加相消的方法,首先我们将第 \(k+1\) 行乘 \(-1\) 倍加到第 \(k\) 行上去可以得到:
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&\cdots&-1\\
0&n-k&\cdots&0&-1&-1&\cdots&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&\cdots&-1\\
0&0&\cdots&0&k&-k&\cdots&0\\
-1&-1&\cdots&-1&0&k&\cdots&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots\\
-1&-1&\cdots&-1&0&0&\cdots&k\\
\end{bmatrix}
\]
再依次将 \(k+2\) 行乘 \(-1\) 倍加到第 \(k+1\) 行上去,第 \(k+3\) 行乘 \(-1\) 倍加到第 \(k+2\) 行上去,依次类推,最终可以得到:
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
0&n-k&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&-1&\cdots&-1&-1\\
0&0&\cdots&0&k&-k&0&\cdots&0&0\\
0&0&\cdots&0&0&k&-k&\cdots&0&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&0&0&0&0&\cdots&k&-k\\
-1&-1&\cdots&-1&0&0&0&\cdots&0&k\\
\end{bmatrix}
\]
然后依次将第 \(1,2,\cdots,k-1\) 行乘 \(\dfrac{1}{n-k}\) 倍加到第 \(n\) 行上去可得
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
0&n-k&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&-1&\cdots&-1&-1\\
0&0&\cdots&0&k&-k&0&\cdots&0&0\\
0&0&\cdots&0&0&k&-k&\cdots&0&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&0&0&0&0&\cdots&k&-k\\
0&0&\cdots&0&-\dfrac{k-1}{n-k}&-\dfrac{k-1}{n-k}&-\dfrac{k-1}{n-k}&\cdots&-\dfrac{k-1}{n-k}&k-\dfrac{k-1}{n-k}\\
\end{bmatrix}
\]
记 \(A=k,B=\dfrac{k-1}{n-k}\),那么该矩阵可写作
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
0&n-k&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&-1&\cdots&-1&-1\\
0&0&\cdots&0&A&-A&0&\cdots&0&0\\
0&0&\cdots&0&0&A&-A&\cdots&0&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&0&0&0&0&\cdots&A&-A\\
0&0&\cdots&0&-B&-B&-B&\cdots&-B&A-B\\
\end{bmatrix}
\]
将第 \(k\) 行乘 \(\dfrac{B}{A}\) 倍加到第 \(n-1\) 行上:
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
0&n-k&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&-1&\cdots&-1&-1\\
0&0&\cdots&0&A&-A&0&\cdots&0&0\\
0&0&\cdots&0&0&A&-A&\cdots&0&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&0&0&0&0&\cdots&A&-A\\
0&0&\cdots&0&0&-2B&-B&\cdots&-B&A-B\\
\end{bmatrix}
\]
将第 \(k+1\) 行乘 \(\dfrac{2B}{A}\) 倍加到第 \(n-1\) 行上:
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
0&n-k&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&-1&\cdots&-1&-1\\
0&0&\cdots&0&A&-A&0&\cdots&0&0\\
0&0&\cdots&0&0&A&-A&\cdots&0&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&0&0&0&0&\cdots&A&-A\\
0&0&\cdots&0&0&0&-3B&\cdots&-B&A-B\\
\end{bmatrix}
\]
以此类推,依次执行“将第 \(k-1+i\) 行乘 \(\dfrac{iB}{A}\) 倍加到第 \(n-1\) 上,\(i\le n-k-1\)”。最后一步进行的应该是将 \(n-2\) 行乘 \(\dfrac{(n-k-1)B}{A}\) 到第 \(n-1\) 行上去。
\[\begin{bmatrix}
n-k&0&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
0&n-k&\cdots&0&-1&-1&-1&\cdots&-1&-1\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&n-k&-1&-1&-1&\cdots&-1&-1\\
0&0&\cdots&0&A&-A&0&\cdots&0&0\\
0&0&\cdots&0&0&A&-A&\cdots&0&0\\
\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots&\vdots\\
0&0&\cdots&0&0&0&0&\cdots&A&-A\\
0&0&\cdots&0&0&0&0&\cdots&0&A-(n-k)B\\
\end{bmatrix}
\]
我们惊奇地发现,\(A-(n-k)B=1\)。
因此该矩阵的行列式就是 \((n-k)^{k-1}\times A^{n-k-1}=(n-1)^{k-1}\times k^{n-k-1}\)
最终答案就是 \((n-k)^{k-1}\times k^{n-k-1}\times\dbinom{n-1}{k-1}\)
代码就不贴了,估计连刚学 OI 的都会写罢(
upd:还是贴了(因为这是我在 Linux VIM 下写出的并用共享文件夹传到 Windows 上的文件(((
#include <bits/stdc++.h>
using namespace std;
int n,k,mod;
int qpow(int x,int e){
int ret=1;
for(;e;e>>=1,x=1ll*x*x%mod) if(e&1) ret=1ll*ret*x%mod;
return ret;
}
namespace Small{
const int MAXN=1000;
int c[MAXN+5][MAXN+5];
void solve(){
for(int i=0;i<=MAXN;i++){
c[i][0]=1;
for(int j=1;j<=i;j++) c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
}
printf("%d\n",1ll*c[n-1][k-1]*qpow(k,n-k-1)%mod*qpow(n-k,k-1)%mod);
}
}
namespace Large{
const int MAXN=5e5;
int fac[MAXN+5],ifac[MAXN+5];
void init_fac(int n){
for(int i=(fac[0]=ifac[0]=ifac[1]=1)+1;i<=n;i++) ifac[i]=1ll*ifac[mod%i]*(mod-mod/i)%mod;
for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i]*ifac[i-1]%mod;
}
void solve(){
init_fac(MAXN);
printf("%d\n",1ll*fac[n-1]*ifac[n-k]%mod*ifac[k-1]%mod*qpow(k,n-k-1)%mod*qpow(n-k,k-1)%mod);
}
}
int main(){//edited in VIM
scanf("%d%d%d",&n,&k,&mod);
if(n<=1000) Small::solve();
else Large::solve();
return 0;
}