其他分享
首页 > 其他分享> > Edge Groups(ICPC)

Edge Groups(ICPC)

作者:互联网

树上计数

考虑如果一个点的亲儿子是偶数个 两两亲儿子配对就好

如果一个点的亲儿子是奇数个 挑一个出来和连上父亲 其余偶数个两两配对

n个两两配对的方案数为 (C(n,2)×C(n-2,2)×...×C(2,2))/((n/2)!)

化简得 (n!)/(2的n/2次方)×((n/2)!)预处理阶乘就好

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int mod=998244353;
const int maxn=1e5+5;
int n;
vector<int>Q[maxn];
ll ans=1;
ll dp[maxn],jc[maxn],vis[maxn],cf[maxn];
ll fast_mi(ll aa, ll bb){
	ll res=1;
	while(bb){
		if(bb&1)res=res*aa%mod;
		bb>>=1;
		aa=aa*aa%mod;
	}
	return res;
}
void dfs(int u,int fa);
ll calc(ll x){
	return jc[x]*fast_mi(cf[x/2]*jc[x/2]%mod,mod-2)%mod;
}
int main(){
	int n;
	jc[0]=1;
	cf[0]=1;
	cin>>n;
	for(int i=1;i<n;i++){
		jc[i]=jc[i-1]*i%mod;
		cf[i]=cf[i-1]*2%mod;
		int a,b;
		cin>>a>>b;
		Q[a].push_back(b);
		Q[b].push_back(a);
	}
	jc[n]=jc[n-1]*n%mod;
	cf[n]=cf[n-1]*2%mod;
	dfs(1,1);
	for(int i=1;i<=n;i++)
	ans=ans*dp[i]%mod;
	cout<<ans<<endl;
     return 0;
}
void dfs(int u,int fa){
	ll res=0;
	ll sz=Q[u].size()-1;
	for(int i=0;i<Q[u].size();i++){
		int to=Q[u][i];
		if(to==fa)continue;
		dfs(to,u);
		res+=vis[to];
	}
	if(u==1)sz++;
	ll t=sz-res;
	if(t&1){
		dp[u]=t*calc(t-1)%mod;
		vis[u]=1;
	}else 
		dp[u]=calc(t); 
}

标签:int,ll,cf,ICPC,Edge,maxn,Groups,jc,mod
来源: https://www.cnblogs.com/wzxbeliever/p/16176735.html