JZOJ.5273【NOIP2017模拟8.14】亲戚

Description

 

Input

Output

 

Sample Input

4
0 1 1 0

Sample Output

8
 

Data Constraint


.对于一棵子树,位于同一个深度的点个数用组合公式,整棵子树节点用排列公式,再随便整理一下就好了......

$\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 }
神奇的代码

这里还有一道不错的类似题目,在这题基础上多了可违反规矩的次数。

posted @ 2017-08-14 19:07  ~Lanly~  阅读(153)  评论(0编辑  收藏  举报