UVa 11174 (乘法逆元) Stand in a Line
2015-03-02 22:13
239 查看
题意:
有n个人排队,要求每个人不能排在自己父亲的前面(如果有的话),求所有的排队方案数模1e9+7的值。
分析:
《训练指南》上分析得挺清楚的,把公式贴一下吧:
设f(i)为以i为根节点的子树的排列方法,s(i)表示以i为根的子树的节点总数。
f(i) = f(c1)f(c2)...f(ck)×(s(i)-1)!/(s(c1)!s(c2)!...s(ck)!)
按照书上最开始举的例子,其实这个式子也不难理解,就是先给这些子树确定一下位置,即有重元素的全排列。
子树的位置确定好以后,然后再确定子树中各个节点的顺序。
对了,因为求组合数会用到除法,而且1e9+7又是个素数,所以我们在做除法的时候只要乘上它对应的乘法逆元即可。
这是递归计算的代码:
代码君
有n个人排队,要求每个人不能排在自己父亲的前面(如果有的话),求所有的排队方案数模1e9+7的值。
分析:
《训练指南》上分析得挺清楚的,把公式贴一下吧:
设f(i)为以i为根节点的子树的排列方法,s(i)表示以i为根的子树的节点总数。
f(i) = f(c1)f(c2)...f(ck)×(s(i)-1)!/(s(c1)!s(c2)!...s(ck)!)
按照书上最开始举的例子,其实这个式子也不难理解,就是先给这些子树确定一下位置,即有重元素的全排列。
子树的位置确定好以后,然后再确定子树中各个节点的顺序。
对了,因为求组合数会用到除法,而且1e9+7又是个素数,所以我们在做除法的时候只要乘上它对应的乘法逆元即可。
这是递归计算的代码:
#include <bits/stdc++.h> using namespace std; const int maxn = 40000 + 10; const int MOD = 1000000007; int n, m; vector<int> sons[maxn]; int fa[maxn], fac[maxn], ifac[maxn], inverse[maxn], sonsize[maxn]; inline int mul_mod(int a, int b, int n = MOD) { a %= n; b %= n; return (int)((long long)a * b % n); } void gcd(int a, int b, int& d, int& x, int& y) { if(!b) { d = a; x = 1; y = 0; } else{ gcd(b, a%b, d, y, x); y -= x*(a/b); } } int inv(int a, int n = MOD) { int d, x, y; gcd(a, n, d, x, y); return d == 1 ? (x+n)%n : -1; } int C(int n, int m) { return mul_mod(mul_mod(fac , ifac[m]), ifac[n-m]); } void init() { fac[0] = ifac[0] = 1; for(int i = 1; i < maxn; i++) { fac[i] = mul_mod(fac[i - 1], i); inverse[i] = inv(i); } } void count(int u, int& size) {//统计以u为根的子树节点个数 size = 1; int d = sons[u].size(); for(int i = 0; i < d; i++) { int sz; count(sons[u][i], sz); size += sz; } sonsize[u] += size; } int main() { //freopen("in.txt", "r", stdin); init(); int T; scanf("%d", &T); while(T--) { memset(fa, 0, sizeof(fa)); memset(sonsize, 0, sizeof(sonsize)); for(int i = 0; i <= n; i++) sons[i].clear(); scanf("%d%d", &n, &m); for(int i = 0; i < m; i++) { int a, b; scanf("%d%d", &a, &b); fa[a] = b; sons[b].push_back(a); } for(int i = 1; i <= n; i++) if(!fa[i]) sons[0].push_back(i); int size; count(0, size); //for(int i = 1; i <= n; i++) printf("%d\n", sonsize[i]); int ans = fac ; for(int i = 1; i <= n; i++) ans = mul_mod(ans, inverse[sonsize[i]]); printf("%d\n", ans); } return 0; }
代码君
相关文章推荐
- uva 11174 - Stand in a Line(求乘法逆元)
- 数学,乘法逆元(Stand in a Line,uva 11174)
- 【递推】【推导】【乘法逆元】UVA - 11174 - Stand in a Line
- UVA 11174 Stand in a Line 树形dp+计数
- UVA 11174 Stand in a Line 树dp+算
- UVA 11174 - Stand in a Line(组合递归计数)
- Stand in a Line UVA11174
- UVa11174 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(逆元+递推)
- UVA - 11174 Stand in a Line
- 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 (数学基础+除法取模)