Stand in a Line UVA11174
2013-01-16 13:56
302 查看
把所有的村民排成一队,所有的父亲必须排在其子孙的前面,有人的父亲不在村子里,求排列的总数,
首先设一个虚拟节点0,表示所有父亲不在村子里的人虚拟父亲,这样所有的点就构成了一棵树,
假设以i为根的子树的排列数为f(i),其节点数为s(i),
考虑一棵以C为根的子树,cj为其孩子,首先每棵以孩子节点为根的子树的排列是相互独立的,满足乘法原理,所以在不考虑子树之间的排列时排列总数为∏f(cj),再考虑吧所有的子孙穿插起来(其中每棵子树子孙的相对位置不变)的排列数,这相当于有重复元素的全排列,所以f(C) = f(c1)*f(c2)...f(cj)*(s(C)-1)!/(s(c1)!s(c2)!...s(cj)!),通过递归式的求解可以化简成为f(root)
= (s(root)-1)!/(s(1)s(2)...s(n))(训练指南上给出的式子有问题),此题要求答案对1000000007取模后的结果,把除法转化成乘以其逆元,所以预处理从1到40000阶乘和其在⊙m下的乘法逆元,m = 1000000007,按照给出的数据带入即可。
首先设一个虚拟节点0,表示所有父亲不在村子里的人虚拟父亲,这样所有的点就构成了一棵树,
假设以i为根的子树的排列数为f(i),其节点数为s(i),
考虑一棵以C为根的子树,cj为其孩子,首先每棵以孩子节点为根的子树的排列是相互独立的,满足乘法原理,所以在不考虑子树之间的排列时排列总数为∏f(cj),再考虑吧所有的子孙穿插起来(其中每棵子树子孙的相对位置不变)的排列数,这相当于有重复元素的全排列,所以f(C) = f(c1)*f(c2)...f(cj)*(s(C)-1)!/(s(c1)!s(c2)!...s(cj)!),通过递归式的求解可以化简成为f(root)
= (s(root)-1)!/(s(1)s(2)...s(n))(训练指南上给出的式子有问题),此题要求答案对1000000007取模后的结果,把除法转化成乘以其逆元,所以预处理从1到40000阶乘和其在⊙m下的乘法逆元,m = 1000000007,按照给出的数据带入即可。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <queue> #include <algorithm> #include <vector> #include <cstring> #include <stack> #include <cctype> #include <utility> #include <map> #include <string> #include <climits> #include <set> #include <string> #include <sstream> #include <utility> #include <ctime> using std::priority_queue; using std::vector; using std::swap; using std::stack; using std::sort; using std::max; using std::min; using std::pair; using std::map; using std::string; using std::cin; using std::cout; using std::set; using std::queue; using std::string; using std::istringstream; using std::make_pair; using std::greater; using std::endl; typedef long long LL; const int MAXN(40010); const LL MOD(1000000007); void egcd(LL a, LL b, LL &x, LL &y, LL &G) { if(!b) { G = a; x = 1; y = 0; } else { egcd(b, a%b, y, x, G); y -= x*(a/b); } } LL inverse(LL a, LL M) { LL x, y, G; egcd(a, M, x, y, G); return G == 1? (x+M)%M: -1LL; } LL fac[MAXN], inv[MAXN]; struct EDGE { int v; EDGE *next; }; EDGE *first[MAXN]; EDGE edge[MAXN]; EDGE *rear; void init() { memset(first, 0, sizeof(first)); rear = edge; } void insert(int tu, int tv) { rear->v = tv; rear->next = first[tu]; first[tu] = rear++; } bool is_root[MAXN]; LL ans; int dfs(int cur) { int ts = 1; for(EDGE *i = first[cur]; i; i = i->next) ts += dfs(i->v); if(cur != 0) ans = ans*inv[ts]%MOD; return ts; } int main() { fac[0] = 1LL; for(int i = 1; i <= 40000; ++i) { fac[i] = fac[i-1]*i%MOD; inv[i] = inverse(i, MOD); } int T; scanf("%d", &T); while(T--) { init(); int n, m; scanf("%d%d", &n, &m); int tu, tv; memset(is_root, -1, sizeof(is_root)); for(int i = 0; i < m; ++i) { scanf("%d%d", &tv, &tu); insert(tu, tv); is_root[tv] = false; } for(int i = 1; i <= n; ++i) if(is_root[i]) insert(0, i); ans = fac ; dfs(0); printf("%lld\n", ans); } return 0; }
相关文章推荐
- UVa 11174 - Stand in a Line
- UVA 11174 Stand in a Line
- uva11174 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 (数学基础+除法取模)
- 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 树dp+算
- 【UVA11174】Stand in a Line——逆元+树形Dp
- UVA11174 J.Stand in a Line (计数+逆元)
- uva 11174 - Stand in a Line(逆元+递推)
- 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 (排列组合)