LOJ #6044 -「雅礼集训 2017 Day8」共(矩阵树定理+手推行列式)

题面传送门

一道代码让你觉得它是道给初学者做的题,然鹅我竟没想到?

首先考虑做一步转化,我们考虑将整棵树按深度奇偶性转化为一张二分图,即将深度为奇数的点视作二分图的左部,深度为偶数的点视作二分图的右部,这样我们肯定只能在左右部点之间连边,这大概算得上一个小套路吧,不过这还是萌新第一次见到这个套路呢,大佬不喜勿喷(

接下来考虑怎么求方案数,显然 \(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;
}
posted @ 2021-05-14 20:46  tzc_wk  阅读(146)  评论(0)    收藏  举报