P13020 [GESP202506 八级] 遍历计数 题解
George__Pig · · 题解
零
虽然本人思路看上去较冗长,但展现的是本人在考场上的一步步简化问题的步骤,希望能给读者带来帮助。
一
首先,考虑以1为起点遍历的情况。考虑树形dp。
令
设
其中
细节看代码(
#define int long long
m=1e9
void dfs(int pos,int fa){
f[pos]=1;
for(auto son:e[pos])
if(son!=fa){
dfs(son,pos);
cnt[pos]++;
f[pos]=f[pos]*f[son]%m;
}
f[pos]=f[pos]*A[cnt[pos]]%m;
}
二
上面的
注意到:
当点
考虑任意一边
以
以
二者相比得:
所以,可以用深搜再跑一遍,计算出每个
但是 模运算不支持除法
三
由上文知
即
而
所求为
注意到
树形
代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
vector<int>e[N];
int n,u,v,A[N],f[N],cnt[N],m=1e9;
void dfs(int pos,int fa){
f[pos]=1;
for(auto son:e[pos])
if(son!=fa){
dfs(son,pos);
cnt[pos]++;
f[pos]=f[pos]*f[son]%m;
}
if(pos!=1) f[pos]=f[pos]*A[cnt[pos]]%m;//f[1]即为上文的λ
else f[pos]=f[pos]*A[cnt[pos]-1]%m;
}
signed main(){
cin>>n;
if(n==1){cout<<1;return 0;} //n=1时没有边,一切免谈
A[0]=1;
for(int i=1;i<=1e5;i++) A[i]=A[i-1]*i%m;
for(int i=1;i<n;i++){
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
cout<<f[1]*(n-1)*2%m;
return 0;
}