【JZOJ6569】【GDOI2020模拟】夕张的改造 (kaisou)

题目大意

给出一棵树,可以删除其中最多(k)条边,再加上若干条边使得其还是一棵树,问这样的操作能得到多少种不同的树的形态(带编号)。

(nleq 50, 0leq k leq n)

思路

一种升级版的生成树计数。
设树上的边权值为(1),不存在的边权值为(x),则构造矩阵(g)

  • (i≠j),则(g[i][j]=)((i,j))的权值的相反数。
  • (i=j),则(g[i][j]=)(i)相邻边的权值之和。
  • 矩阵树定理:构造上述矩阵后,该矩阵其任意一个余子式的行列式(=sum_{所有生成树}边权之积)
  • 求行列式的方法:用高斯消元把矩阵消成上三角矩阵后,对角线数字乘积即为其行列式的值。

现在(x)不确定,所以求出来的行列式实际上是一个多项式。这个多项式的(x^k)的系数,就是使用(k)条边权为(x)的边的方案数,即删去原树中(k)条边,再加上(k)条边形成一棵树的方案数。那么问题就变成求这个多项式的系数了。
直接求系数不好做,我们可以考虑先求这个多项式的点值表达,即把(x)分别代换成(n)个不同的数求行列式,然后使用高斯消元或拉格朗日插值法还原系数表达。
最后把(x^0)(x^k)的系数加起来就是答案了。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long ll;
const int N=57;
const ll P=998244353;

int n,K;
int a[N][N],f[N];
ll sum,g[N][N][2],b[N][N],y[N],ans[N];
ll mtp[N],tmp[N],mtp1[N];

ll pow(ll a,ll b){
	ll ret=1;
	for(;b;a=a*a%P,b>>=1)if(b&1)ret=ret*a%P;
	return ret;
}
ll inv(ll x){return pow(x%P,P-2);}

ll solve(){
	for(int i=1;i<n;++i){
		for(int j=i+1;j<n;++j){
			ll res=b[j][i]*inv(b[i][i])%P;
			for(int k=1;k<n;++k)b[j][k]=(b[j][k]-res*b[i][k]%P+P)%P;
		}
	}
	ll ret=1;
	for(int i=1;i<n;++i)ret=ret*b[i][i]%P;
	return ret;
}

void domtp(){
	memset(tmp,0,sizeof(tmp));
	for(int i=0;i<n;++i)for(int j=0;j<2;++j)tmp[i+j]=(tmp[i+j]+mtp[i]*mtp1[j]%P)%P;
	memcpy(mtp,tmp,sizeof(tmp));
}

int main(){
	freopen("kaisou.in","r",stdin);
	//freopen("kaisou.out","w",stdout);
	scanf("%d%d",&n,&K);
	for(int i=2;i<=n;++i)scanf("%d",&f[i]),++f[i],a[i][f[i]]=a[f[i]][i]=1;
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)--g[i][j][a[i][j]],++g[i][i][a[i][j]];
	for(int i=1;i<=n;++i){
		for(int j=1;j<=n;++j)for(int k=1;k<=n;++k)b[j][k]=((g[j][k][0]+P)*i+(g[j][k][1]+P)%P)%P;
		y[i]=solve();
	}
	for(int i=1;i<=n;++i){
		ll pp=1;
		memset(mtp,0,sizeof(mtp));
		mtp[0]=1;
		for(int j=1;j<=n;++j)if(j!=i){
			mtp1[1]=1,mtp1[0]=P-j;
			domtp();
			pp=pp*(i-j+P)%P;
		}
		for(int j=0;j<n;++j)ans[j]=(ans[j]+mtp[j]*inv(pp)%P*y[i]%P)%P;
	}
	for(int i=0;i<=K;++i)sum=(sum+ans[i])%P;
	printf("%lld
",sum);
	return 0;
}

原文地址:https://www.cnblogs.com/zjlcnblogs/p/12748500.html