JZOJ.5273【NOIP2017模拟8.14】亲戚
.对于一棵子树,位于同一个深度的点个数用组合公式,整棵子树节点用排列公式,再随便整理一下就好了......
$\dfrac {n!} {\prod _{i=1}^{n}S\left( i\right) }$ 其中 $S\left( i\right)$表示以i为根节点的子树的点的个数
除法的逆元一下就行了。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #define N 200005 7 #define mo 1000000007 8 using namespace std; 9 int n,s[N],chu[N],next[N*2],head[N],to[N*2],num; 10 long long ans; 11 void add(int u,int v){ 12 num++; 13 next[num]=head[u]; 14 to[num]=v; 15 head[u]=num; 16 } 17 void dfs(int x){ 18 if (chu[x]==0) { 19 s[x]=1; 20 return; 21 } 22 for (int i=head[x];i;i=next[i]){ 23 dfs(to[i]); 24 s[x]+=s[to[i]]; 25 } 26 s[x]++; 27 } 28 void kuai(int x,int b){ 29 long long a=1,qwq=b,qaq=x; 30 while (qwq){ 31 if (qwq&1) a=(qaq*a)%mo; 32 qwq>>=1; 33 qaq=(qaq*qaq)%mo; 34 } 35 ans=(ans*a)%mo; 36 } 37 int main(){ 38 scanf("%d",&n); 39 num=0; 40 for (int i=1,u=0;i<=n;i++){ 41 scanf("%d",&u); 42 add(u,i); 43 chu[u]++; 44 } 45 dfs(0); 46 ans=1; 47 for (int i=1;i<=n;i++) 48 ans=(i%mo*ans)%mo; 49 for (int i=1;i<=n;i++) 50 if (s[i]!=1) 51 kuai(s[i],mo-2); 52 printf("%lld",ans); 53 return 0; 54 }
这里还有一道不错的类似题目,在这题基础上多了可违反规矩的次数。