您的位置:首页 > 其它

UVa11174 Stand in a Line

2017-01-11 23:36 344 查看

数学问题 排列

设以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

/*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#define LL long long
using namespace std;
const int mod=1000000007;
const int mxn=40010;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m;
int jc[mxn],ny[mxn];
int fa[mxn];
vector<int>e[mxn];
void exgcd(int a,int b,int &x,int &y){
if(!b){x=1;y=0;return;}
exgcd(b,a%b,y,x);
y-=a/b*x;
return;
}
LL f[mxn];
LL DFS(int u){
if(f[u])return f[u];
f[u]++;
for(int i=0;i<e[u].size();i++)
f[u]+=DFS(e[u][i]);
return f[u];
}
void init(){
jc[1]=1;int x,y;
for(int i=2;i<mxn;i++)
jc[i]=((LL)jc[i-1]*i)%mod;
for(int i=1;i<mxn;i++){
exgcd(i,mod,x,y);
ny[i]=(x%mod+mod)%mod;
}
return;
}
int main(){
init();
int T=read();
int i,j,u,v;
while(T--){
n=read();m=read();
for(i=0;i<=n;i++) e[i].clear();
memset(f,0,sizeof f);
for(i=1;i<=m;i++){
u=read();v=read();
e[v].push_back(u);
}
LL ans=1;
for(i=1;i<=n;i++)ans=(ans*i)%mod;
for(i=1;i<=n;i++)ans=ans*ny[DFS(i)]%mod;
printf("%lld\n",ans);
}
return 0;
}

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: