UVa11174 Stand in a Line

数学问题 排列

设以i为根的子树有f[i]种排法,f[i]=(size[i]-1)!*f(c1)*f(c2)*f(c3).../size(c1)!/size(c2)!/size(c3)!/...

其中c表示i的子结点。

将f[c]的表达式带进去,最终会化简成:f[root]=(size(root)-1)!/size(c1)/size(c2)/size(c3)/....

在模的意义下涉及到除法,需要求逆元。

 

↓代码里的f表示size

 1 /*by SilverN*/
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 #define LL long long
 9 using namespace std;
10 const int mod=1000000007;
11 const int mxn=40010;
12 int read(){
13     int x=0,f=1;char ch=getchar();
14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 int n,m;
19 int jc[mxn],ny[mxn];
20 int fa[mxn];
21 vector<int>e[mxn];
22 void exgcd(int a,int b,int &x,int &y){
23     if(!b){x=1;y=0;return;}
24     exgcd(b,a%b,y,x);
25     y-=a/b*x;
26     return;
27 }
28 LL f[mxn];
29 LL DFS(int u){
30     if(f[u])return f[u];
31     f[u]++;
32     for(int i=0;i<e[u].size();i++)
33         f[u]+=DFS(e[u][i]);
34     return f[u];
35 }
36 void init(){
37     jc[1]=1;int x,y;
38     for(int i=2;i<mxn;i++)
39         jc[i]=((LL)jc[i-1]*i)%mod;
40     for(int i=1;i<mxn;i++){
41         exgcd(i,mod,x,y);
42         ny[i]=(x%mod+mod)%mod;
43     }
44     return;
45 }
46 int main(){
47     init();
48     int T=read();
49     int i,j,u,v;
50     while(T--){
51         n=read();m=read();
52         for(i=0;i<=n;i++) e[i].clear();
53         memset(f,0,sizeof f);
54         for(i=1;i<=m;i++){
55             u=read();v=read();
56             e[v].push_back(u);
57         }
58         LL ans=1;
59         for(i=1;i<=n;i++)ans=(ans*i)%mod;
60         for(i=1;i<=n;i++)ans=ans*ny[DFS(i)]%mod;
61         printf("%lld\n",ans);
62     }
63     return 0;
64 }

 

posted @ 2017-01-11 23:36  SilverNebula  阅读(195)  评论(0编辑  收藏  举报
AmazingCounters.com