数学问题 排列
设以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 }