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的大小影响的 所以要状压这个除法操作. 直接采 ...
随机推荐
- SVN常见问题处理
1.SVN 提交时报错:Path is not a working copy directory (1)报这个错通常是因为这个文件夹或其上层文件夹不是checkout或update出来的. 使用S ...
- OpenGL第18,19,20讲小结
18讲是通过调用库函数画一些简单的二次几何体,比如球体.圆锥体.圆盘等等. 19讲简单的讲了下粒子系统.其实就是三角形贴上星星的纹理,通过启用混合(GL_BLEND)来达到一种动态的粒子效果.通过修改 ...
- Vs2010搭建directshow 环境
一:材料 1, vs2010 2, winsdk7.1 http://www.microsoft.com/en-us/download/details.aspx?id=8442 更具自己电脑选择32 ...
- 【风马一族_xml】xml的两种解析思想
xml的解析思想 dom解析 将整个xml使用类似树的结构保存在内存中,再进行对其操作 是woc组织推荐的处理xml的一种方式 需要等到xml完全加载进内存才可以进行操作 耗费内存.当解析超大的xml ...
- C++与Java多态的区别
多态是指用父指针指向不同子类对象时,调用其共有的函数,不同的子类会有不同的行为.虽然C++和Java都具有多态机制,但是他们的实现不同,使用时的效果也会略有不同. 在C++中 普通函数调用:具体调用哪 ...
- 简单的jQuery获取URL的?后带的参数
var con_name = getQueryString("con_name"); //接收con_name function getQueryString(val ...
- 第一个C#应用 【搜索软件】
搜索软件V1.0 [附软件截图][http://pan.baidu.com/s/1mihEbe4] 设备搜索:支持广播搜索[local search],指定ip[range search]搜索,直接w ...
- redis 界面软件使用
ubuntu 下下载安装包 sudo dpkg -i redis-desktop-manager_0.8.3-120_amd64.deb//安装 redis-desktop-manager //启动
- 命令行插入含有中文的sql文件,报错ERROR 1366 (HY000): Incorrect stringvalue:
--以下是插入语句: insert into sms_inbox values('123456','123456', 'cd', sysdate(), '今天天 气很好', 1, sysdate(), ...
- range,shuffle,str_shuffle
print_r(range(1,20)); 输出,range产生 Array( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 ...