题意:村子里有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 (组合+除法的求模)的更多相关文章

  1. uva 11174 Stand in a Line

    // uva 11174 Stand in a Line // // 题目大意: // // 村子有n个村民,有多少种方法,使村民排成一条线 // 使得没有人站在他父亲的前面. // // 解题思路: ...

  2. UVA 11174 Stand in a Line 树上计数

    UVA 11174 考虑每个人(t)的所有子女,在全排列中,t可以和他的任意子女交换位置构成新的排列,所以全排列n!/所有人的子女数连乘   即是答案 当然由于有MOD 要求逆. #include & ...

  3. uva 11174 Stand in a Line (排列组合)

    UVa Online Judge 训练指南的题目. 题意是,给出n个人,以及一些关系,要求对这n个人构成一个排列,其中父亲必须排在儿子的前面.问一共有多少种方式. 做法是,对于每一个父节点,将它的儿子 ...

  4. UVA 11174 Stand in a Line 树dp+算

    主题链接:点击打开链接 题意:白书的P103. 加个虚根就能够了...然后就是一个多重集排列. import java.io.PrintWriter; import java.util.ArrayLi ...

  5. 【递推】【推导】【乘法逆元】UVA - 11174 - Stand in a Line

    http://blog.csdn.net/u011915301/article/details/43883039 依旧是<训练指南>上的一道例题.书上讲的比较抽象,下面就把解法具体一下.因 ...

  6. UVA 11174 Stand in a Line,UVA 1436 Counting heaps —— (组合数的好题)

    这两个题的模型是有n个人,有若干的关系表示谁是谁的父亲,让他们进行排队,且父亲必须排在儿子前面(不一定相邻).求排列数. 我们假设s[i]是i这个节点,他们一家子的总个数(或者换句话说,等于他的子孙数 ...

  7. LeetCode 29 Divide Two Integers (不使用乘法,除法,求模计算两个数的除法)

    题目链接: https://leetcode.com/problems/divide-two-integers/?tab=Description   Problem :不使用乘法,除法,求模计算两个数 ...

  8. 数学:UVAoj 11174 Stand in a Line

    Problem J Stand in a Line Input: Standard Input Output: Standard Output All the people in the bytela ...

  9. 3.29省选模拟赛 除法与取模 dp+组合计数

    LINK:除法与取模 鬼题.不过50分很好写.考虑不带除法的时候 其实是一个dp的组合计数. 考虑带除法的时候需要状压一下除法操作. 因为除法操作是不受x的大小影响的 所以要状压这个除法操作. 直接采 ...

随机推荐

  1. zz 如何在Linux下创建与解压zip, tar, tar.gz和tar.bz2文件

    January 2nd, 2009 at 10:31 pm Linux 解压, Linux, tar, tar.bz2, tar.gz, tgz, zip, 压缩, 打包, 文档 这么多年来,数据压缩 ...

  2. 简单的jQuery获取URL的?后带的参数

    var con_name = getQueryString("con_name"); //接收con_name        function getQueryString(val ...

  3. C#简单实现发送手机短信

    偶然想起,像编写一个从电脑向手机发送短信的程序,从网上查找到有三种方式:(1)使用webservice接口发送手机短信,这个可以使用sina提供的webservice进行发送,但是需要进行注册;(2) ...

  4. Ubuntu下设置Tomcat成为服务(开机启动)

    1.将tomcat安装目录下bin文件夹中的catalina.sh拷贝到/etc/init.d下并修改名称为tomcat cp  /path/to/tomcat/bin/catalina.sh /et ...

  5. Linux大量TIME_WAIT的解决办法

    发布:theboy   来源:net   [大 中 小] 根据TCP协议定义的3次握手断开连接规定,发起socket主动关闭的一方 socket将进入TIME_WAIT状态,TIME_WAIT状态将持 ...

  6. Azure Websites Migration Assistant

    这是一个IIS+Database的迁移工具, 可以参考 http://channel9.msdn.com/Shows/Azure-Friday/Azure-Websites-Migration-Ass ...

  7. ALTER TABLE causes auto_increment resulting key 'PRIMARY'

    修改表为主键的自动增长值时,报出以下错误:mysql> ALTER TABLE YOON CHANGE COLUMN id id INT(11) NOT NULL AUTO_INCREMENT ...

  8. How to install DIG dns tool on windows 7

    This guide explain how to install dig dns tool on windows 7 in few steps: 1. First go to http://www. ...

  9. asp.net 多个域名重定向,在web.Config中配置

    一个网站有多个域名,但是需要在访问其中某个域名之后跳转到另一域名. Web.config 中配置 </system.webServer> <!--重定向 域名 开始--> &l ...

  10. AJAX请求遭遇未登录和Session失效的解决方案

    使用技术:HTML + Servlet + Filter + jQuery 一般来说我们的项目都有登录过滤器,一般请求足以搞定.但是AJAX却是例外的,所以解决方法是设置响应为session失效. 一 ...