UVA11174 Stand in a Line
2018-01-18 17:09
316 查看
Stand in a Line
大意:有n个人排队,问有多少种排列使得没有人排在他的父亲前面不难发现这是一个森林
设一个虚根root把所有树的根连起来,root排在所有方案的最前面,总方案数不变
设i的儿子为son1(i),son2(i)....sonk(i),k位i儿子的数量
设size[i]为i这棵子树的节点个数
f[i]为i这颗子树的方案数
f[i] = f[son1[i]] * f[son2[i]] * ... * f[sonk[i]] * (size[i] - 1) / (size[son1[i]]! * size[son2[i]]! * .. * size[sonk[i]]!)
相当于每颗子树内部排列:f[son1[i]] * f[son2[i]] * ... * f[sonk[i]]
然后把同一颗子树看做相同的排:(size[i] - 1) / (size[son1[i]]! * size[son2[i]]! * .. * size[sonk[i]]!)
把f[son1[i]]...f[sonk[i]拆开,带进去
发现size[i]!作为分母出现一次,(size[i]-1)!作为分母出现一次,约分得size[i]
于是f[root] = (size[root] - 1)!/(size[son1[i]] * size[son2[i]] * ... * size[sonk[i]])
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> #include <vector> #include <cmath> #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) > (b) ? (a) : (b)) #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) inline void swap(long long &a, long long &b) { long long tmp = a;a = b;b = tmp; } inline void read(long long &x) { x = 0;char ch = getchar(), c = ch; while(ch < '0' || ch > '9') c = ch, ch = getchar(); while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); if(c == '-') x = -x; } const long long INF = 0x3f3f3f3f; const long long MAXN = 100000 + 10; const long long MOD = 1000000007; struct Edge { long long u,v,nxt; Edge(long long _u, long long _v, long long _nxt){u = _u;v = _v;nxt = _nxt;} Edge(){} }edge[MAXN << 1]; long long head[MAXN], cnt; inline void insert(long long a, long long b) { edge[++cnt] = Edge(a,b,head[a]); head[a] = cnt; } long long f[MAXN],t,n,m,b[MAXN],size[MAXN],fa[MAXN]; void dfs(long long u) { size[u] = 1;b[u] = 1; for(register long long pos = head[u];pos;pos = edge[pos].nxt) { long long v = edge[pos].v; if(b[v]) continue; dfs(v), size[u] += size[v]; } return; } long long pow(long long a, long long b) { long long r = 1, base = a%MOD; for(;b;b >>= 1) { if(b & 1) r *= base, r %= MOD; base *= base, base %= MOD; } return r; } long long ni(long long x) { return pow(x, MOD - 2); } int main() { read(t); f[0] = 1; for(register long long i = 1;i < MAXN;++ i) f[i] = (f[i - 1] * i) % MOD; for(;t;--t) { memset(fa, 0, sizeof(fa));memset(head, 0, sizeof(head)), memset(b, 0, sizeof(b)), cnt = 0; read(n), read(m); for(register long long i = 1;i <= m;++ i) { long long tmp1,tmp2; read(tmp1), read(tmp2); insert(tmp2, tmp1); fa[tmp1] = tmp2; } for(register long long i = 1;i <= n;++ i) if(!b[i]) { int now = i; while(fa[now]) now = fa[now]; dfs(now); } long long ans = 1; for(register long long i = 1;i <= n;++ i) ans *= size[i], ans %= MOD; printf("%lld\n", f * ni(ans) % MOD); } return 0; }
UVA11174
相关文章推荐
- uva 11174 - Stand in a Line(逆元+递推)
- UVa11174 Stand in a Line
- uva 11174 - Stand in a Line(求乘法逆元)
- 数学,乘法逆元(Stand in a Line,uva 11174)
- 【递推】【推导】【乘法逆元】UVA - 11174 - Stand in a Line
- UVA 11174 - Stand in a Line(组合递归计数)
- uva11174 Stand in a Line
- uva 11174 Stand in a Line (排列组合)
- UVa 11174 - Stand in a Line
- 【UVA11174】Stand in a Line——逆元+树形Dp
- Uva 11174 Stand in a Line 解题报告(递推+逆元)
- UVa 11174 Stand in a Line
- UVA 11174 - Stand in a Line (数学基础+除法取模)
- UVA 11174 - Stand in a Line (数学基础+除法取模)
- UVa 11174 (乘法逆元) Stand in a Line
- UVA 11174 Stand in a Line 树dp+算
- UVA - 11174 Stand in a Line
- UVA 11174 Stand in a Line——组合数+取模
- UVA 11174 Stand in a Line 树形dp+计数
- UVA11174 J.Stand in a Line (计数+逆元)