UVA 11174 Stand in a Line (组合+除法的求模)
题意:村子里有n个人,给出父亲和儿子的关系,有多少种方式可以把他们排成一列,使得没人会排在他父亲的前面
思路:设f[i]表示以i为根的子树有f[i]种排法,节点i的各个子树的根节点,即它的儿子为c1,c2,c3...ck。
那么先给节点i的子树确定各自的顺序,为f(c1),f(c2)...f(ck)。
然后把每棵子树的所有节点看成同一元素,根据有重复元素的全排列方式共有s(i-1)!/(s(c1)!*s(c2)!*...*s(ck)!)
再根据乘法原理,f[i]=f(c1)* f(c2) *f(c3) * f(c4).....* f(ck) * (s(i) - 1)! / ((s(c1)! * (s(c2))! .... * (s(ck))!) 其中,s[i]表示以i为根的子树的节点个数。
然后观察这个式子,将每个非根节点带入上式子,可发现每个非根节点u以(s(u) - 1)!的形式出现在分子一次,以s(u)!的形式出现在分母一次。
约分后相当于分子为1,分母为s(u),得到最终的式子是: f(i) = (s(i)-1)!/(s(1) * s(2) *... *s(k)) (1,2,3...k为以i为根的子树的所有节点,不包括i)
这样,我们可以设立一个虚父节点root=0,把森林连接起来成为一棵树,这样所求的答案即为: f(root) = (s(root)-1)!/(s(1) * s(2) *... *s(n))
但是最后要让我们求模,而式子中有除法,所以要用到以下定理: a = (b/c) ==> a%m = b*c^(m-2)%m ( m为素数 )
证明如下: b = a * c 根据费马小定理 a^(p-1)= 1 %p (p是素数且a不能整除p) 所以 c^(m-1)%m=1%m
因此 a % m = a*1%m = a * c^(m-1)%m = a*c*c^(m-2)%m = b*c^(m-2)%m;
#include <iostream>
#include <stdio.h>
#include <vector>
/*
组合+除法的求模 题意:
村子里有n个人,给出父亲和儿子的关系,有多少种方式可以把他们排成一列,使得没人会排在他父亲的前面 思路:
设f[i]表示以i为根的子树有f[i]种排法,节点i的各个子树的根节点,即它的儿子为c1,c2,c3...ck。
那么先给节点i的子树确定各自的顺序,为f(c1),f(c2)...f(ck)。
然后把每棵子树的所有节点看成同一元素,根据有重复元素的全排列方式共有s(i-1)!/(s(c1)!*s(c2)!*...*s(ck)!)
再根据乘法原理,f[i]=f(c1)* f(c2) *f(c3) * f(c4).....* f(ck) * (s(i) - 1)! / ((s(c1)! * (s(c2))! .... * (s(ck))!)
其中,s[i]表示以i为根的子树的节点个数。 然后观察这个式子,将每个非根节点带入上式子,可发现每个非根节点u以(s(u) - 1)!的形式出现在分子一次,以s(u)!的形式出现在分母一次。
约分后相当于分子为1,分母为s(u),得到最终的式子是:
f(i) = (s(i)-1)!/(s(1) * s(2) *... *s(k)) (1,2,3...k为以i为根的子树的所有节点,不包括i) 这样,我们可以设立一个虚父节点root=0,把森林连接起来成为一棵树,这样所求的答案即为:
f(root) = (s(root)-1)!/(s(1) * s(2) *... *s(n)) 但是最后要让我们求模,而式子中有除法,所以要用到以下定理:
a = (b/c) ==> a%m = b*c^(m-2)%m ( m为素数 ) 证明如下:
b = a * c
根据费马小定理 a^(p-1)= 1 %p (p是素数且a不能整除p)
所以 c^(m-1)%m=1%m
因此 a % m = a*1%m = a * c^(m-1)%m = a*c*c^(m-2)%m = b*c^(m-2)%m; */
using namespace std;
const long long mod=;
const int maxn=;
vector<int> son[maxn]; //存储儿子节点
int num[maxn]; //存储以i为根的子树的节点个数,包括节点i
int n,m;
long long sum; //求(s(1) * s(2) *... *s(n)) //快速幂,求sum^(mod-2)%mod
long long quickPow(long long a,long long b){
long long ans=;
while(b){
if(b&)
ans=(ans*a)%mod;
a=(a*a)%mod;
b=b>>;
}
return ans;
}
//预处理求阶乘
void init(){
f[]=;
for(int i=;i<maxn;i++){
f[i]=(f[i-]*i)%mod;
}
}
//递归计算子树的节点个数
int dfs(int u){
if(son[u].empty()){
num[u]=;
return num[u];
}
int v;
for(int i=;i<son[u].size();i++){
v=son[u][i];
num[u]+=dfs(v);
}
num[u]++;
return num[u];
}
int main()
{
int t,a,b;
long long ans;
init();
scanf("%d",&t);
while(t--){
for(int i=;i<=n;i++){
num[i]=;
son[i].clear();
}
scanf("%d%d",&n,&m);
for(int i=;i<m;i++){
scanf("%d%d",&a,&b);
son[b].push_back(a);
fa[a]=b;
}
//设立虚父节点0
for(int i=;i<=n;i++){
if(!fa[i]){
son[].push_back(i);
}
}
dfs();
sum=;
for(int i=;i<=n;i++)
sum=(sum*num[i])%mod;
ans=(f[n]*quickPow(sum,mod-))%mod;
printf("%lld\n",ans);
}
return ;
}
UVA 11174 Stand in a Line (组合+除法的求模)的更多相关文章
- uva 11174 Stand in a Line
// uva 11174 Stand in a Line // // 题目大意: // // 村子有n个村民,有多少种方法,使村民排成一条线 // 使得没有人站在他父亲的前面. // // 解题思路: ...
- UVA 11174 Stand in a Line 树上计数
UVA 11174 考虑每个人(t)的所有子女,在全排列中,t可以和他的任意子女交换位置构成新的排列,所以全排列n!/所有人的子女数连乘 即是答案 当然由于有MOD 要求逆. #include & ...
- uva 11174 Stand in a Line (排列组合)
UVa Online Judge 训练指南的题目. 题意是,给出n个人,以及一些关系,要求对这n个人构成一个排列,其中父亲必须排在儿子的前面.问一共有多少种方式. 做法是,对于每一个父节点,将它的儿子 ...
- UVA 11174 Stand in a Line 树dp+算
主题链接:点击打开链接 题意:白书的P103. 加个虚根就能够了...然后就是一个多重集排列. import java.io.PrintWriter; import java.util.ArrayLi ...
- 【递推】【推导】【乘法逆元】UVA - 11174 - Stand in a Line
http://blog.csdn.net/u011915301/article/details/43883039 依旧是<训练指南>上的一道例题.书上讲的比较抽象,下面就把解法具体一下.因 ...
- UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)
这两个题的模型是有n个人,有若干的关系表示谁是谁的父亲,让他们进行排队,且父亲必须排在儿子前面(不一定相邻).求排列数. 我们假设s[i]是i这个节点,他们一家子的总个数(或者换句话说,等于他的子孙数 ...
- LeetCode 29 Divide Two Integers (不使用乘法,除法,求模计算两个数的除法)
题目链接: https://leetcode.com/problems/divide-two-integers/?tab=Description Problem :不使用乘法,除法,求模计算两个数 ...
- 数学:UVAoj 11174 Stand in a Line
Problem J Stand in a Line Input: Standard Input Output: Standard Output All the people in the bytela ...
- 3.29省选模拟赛 除法与取模 dp+组合计数
LINK:除法与取模 鬼题.不过50分很好写.考虑不带除法的时候 其实是一个dp的组合计数. 考虑带除法的时候需要状压一下除法操作. 因为除法操作是不受x的大小影响的 所以要状压这个除法操作. 直接采 ...
随机推荐
- CityEngine2012(32位)安装
今天下午把CityEngine2012装好了,既然Esri大力推CityEngine作为其三维建模软件,那就学习一下,还好没花多长时间搞定破解版,以前装Erdas,南方CASS,AutoCAD那些该死 ...
- 济南学习 Day 1 T2 am
死亡[问题描述]现在有M个位置可以打 sif,有N +1个人在排队等着打 sif.现在告诉你 个人每个人需要多长的时间打 sif,问你第N +1个人什么时候才能打 sif. (前N个人必须按照顺序来) ...
- poj 3669 Meteor Shower
Me ...
- Vs2010搭建directshow 环境
一:材料 1, vs2010 2, winsdk7.1 http://www.microsoft.com/en-us/download/details.aspx?id=8442 更具自己电脑选择32 ...
- Source Insight建工程之Kernel
不管你是从事于Linux内核工作还是出于兴趣爱好,Linux内核源码都是非常好的学习资源.意味着就要经常的和内核源码大交道,那么软件工具就是少不了的.在Windows系统上确实有着许多好用的软件 ...
- Linux系统环境变量及命令
Linux哪些我们常用,但是用的时候想不起来,这里做一个备忘录. Linux常用的变量: PATH 决定了shell将到哪些目录中寻找命令或程序 HOME 当前用户主目录 HISTSIZE 历史记录数 ...
- js设计模式(5)---外观模式
0.前言 早上好,今天天气不错,估计有35度吧,坐在空调室里相当惬意,那么酒足饭饱之后就应该干些正事了. 1. 为什么使用外观模式 外观模式提供了一个高层接口,封装一些复杂操作或繁琐行为,方便调用.门 ...
- for xml path以及sql合并查询
sql中for xml path的用法. http://www.cnblogs.com/yanghaibo/archive/2010/06/04/1751405.html
- mac os使用homebrew来管理后台服务
在linux下我们经常通过 service 或者 /etc/init.d/来管理我们的后台服务软件,并使用包管理器安装这些软件. 在mac下有homebrew这个好用的工具来安装软件,但是一直没有找到 ...
- Jquery LigerUI框架学习(一)
ligerUI框架是一个很丰富的后台框架模板,具有简洁大方的后台样式框架,还有很多灵活的控件,方便开发人员使用: 把昨天学习的成功拿出来供大家学习学习: 首先我们要去ligerUI官网下载Jquery ...