专栏文章
P13020 [GESP202506 八级] 遍历计数 题解
P13020题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mip0hdb8
- 此快照首次捕获于
- 2025/12/03 04:09 3 个月前
- 此快照最后确认于
- 2025/12/03 04:09 3 个月前
零
虽然本人思路看上去较冗长,但展现的是本人在考场上的一步步简化问题的步骤,希望能给读者带来帮助。
一
首先,考虑以1为起点遍历的情况。考虑树形dp。
令以 为顶点的子树的不同方案数
设 的儿子为 ,则有
设 的儿子为 ,则有
其中 表示 的全排列数量
细节看代码( 数组预处理即可):
CPP#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;
}
二
上面的 时间复杂度为 , 个顶点肯定过不了100%
注意到:


当点 之间有边相连时,分别以 为根遍历,得到的 数组只有 发生改变。希望找到二者的关系
考虑任意一边 ,设两点度数为
考虑任意一边 ,设两点度数为

以 为节点时
以 为节点时
二者相比得:
所以,可以用深搜再跑一遍,计算出每个
但是 模运算不支持除法
三
由上文知
即
而 与 无关
令 则
所求为
注意到 故所求为
树形跑出 即可
代码:
CPP#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;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...