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的大小影响的 所以要状压这个除法操作. 直接采 ...
随机推荐
- mongodb gdal 矢量数据格式驱动
写了个mongodb的gdal driver,放在了github上,如果你需要,欢迎加入mongogis group. 直接的效果是使得QGIS, GeoServer, MapServer, ArcG ...
- Linux 输入子系统
Technorati 标签: Kernel 输入子系统 Input 在Linux中,输入设备(如按键.键盘.触摸屏.鼠标等)是典型的字符设备,其一般的工作机理,是底层在按键.触摸时,触发一个 ...
- 判断不在Update Task中
CALL FUNCTION 'TH_IN_UPDATE_TASK' IMPORTING IN_UPDATE_TASK = IN_UPDATE_TASK. "0 then not ...
- ☆RHEL6创建软raid的使用☆——经典之作
raid主要的种类 1.raid0 扩展卷 raid 0又称Stripee或Striping,中文译为集带工作方式, 有时也可以理解为拼凑. 它是将要存取的数据以条带状的形式尽量平均分配到多个硬 ...
- VIM小技巧之文件名补全
恩,这两天在看<简明Python教程>,那里面作者建议写代码的时候前面的注释写上文件名,写上调用的解释器,比如这样: 恩,然后我当然不可能每回新建一个文件,就要在开头写上一大串东西啊,vi ...
- 看部电影,透透彻彻理解IoC(你没有理由再迷惑!)
引述:IoC(控制反转:Inverse of Control)是Spring容器的内核,AOP.声明式事务等功能在此基础上开花结果.但是IoC这个重要的概念却比较晦涩隐讳,不容易让人望文生义,这不能不 ...
- html5 app开发重大消息-腾讯在技术端推进Html5生态发展
中新网5月3日电 日前,腾讯正式发布腾讯浏览服务(Tencent Browser Service,以下简称TBS),宣布为合作伙伴提供整合腾讯底层技术.内容框架.广告体系以及大数据等多方面能力的升级浏 ...
- 解决Win7下运行php Composer出现SSL报错的问题
以前都在linux环境使用php composer.今天尝试在win7下运行composer却出现SSL报错: D:\data\www\mmoyu\symapp>php -f %phprc%\c ...
- 使用mysql关键字做类字段名报的错,花了我一个钟,坑啊
com.modelsystem.po.ProjectPlan@701faaedHibernate: insert into ld.project_plan (addTime, describe, ex ...
- 关于C语言中的typedef
在C语言中定义一个结构体,要最好使用typedef,使用typedef,实际上就是为我们的结构体起了一个新的名字,即定义了一个新的类型,在后面书写自己代码的时候,就可以直接使用自己定义的新的类型第一变 ...