【递推】【推导】【乘法逆元】UVA - 11174 - Stand in a Line
http://blog.csdn.net/u011915301/article/details/43883039
依旧是《训练指南》上的一道例题。书上讲的比较抽象,下面就把解法具体一下。因为涉及到父子关系,因此自然而然可以将n个节点构造成一棵树,最后将形成一个森林。接下来将使用递归的手法。设f(i)是以节点i为树根的子树,节点i有儿子c1,c2,c3....cj共j棵子树。s[i]为树根为i的子树包含的节点数。如果分别先给各个子树内部排序,那么毫无疑问,
共有f(c1)*f(c2)*f(c3)....*f(cj)种情况。接下来又要将所有子树的节点排成一个序列。那么我们事先不考虑各个子树的内部排序,共有(s[i]-1)!/(s[c1]!*s[c2]!*.....s[cj]!种情况。最后,我们将两种情况合起来,就是f(i)的解了,为f(c1)*f(c2)....*f(cj)*(s[i]-1)!/(s[c1]!*s[c2]!*.....s[cj]!)中情况。
事实上,接下来还可以进一步化简,设c1有孩子节点x1,x2,x3....xk。那么f(c1)=f(x1)*f(x2).....f(xk)*(s[c1]-1)!/(s[x1]!*x[x2]!....*x[xk]!)。将f(c1)代入,分子中的(s[c1]-1)!和分母中的s[c1]!约分的s[c1],然后依次类推,最后分母必然会化为s[1]*s[2]*s[3]...s[n]。因为总共n个节点构成一个森林,因此s[root](root可能为虚拟树根)为n+1,那么最后分母为n!。最后,求出n!/(s[1]*s[2]...s[n])就是我们要求的解。
还要注意的是,最后模运算的时候,1的逆为1。
还有一种理解就是C(11,3)*C(8,6)*5*4*1……就是第一颗子树的结点在11个位子里面选三个,第二颗子树的结点在剩下的8个位子里选6个……然后再乘上每颗子树内部的顺序。
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
#define MOD 1000000007ll
ll Quick_Pow(ll a,ll p)
{
if(!p) return 1;
ll ans=Quick_Pow(a,p>>1);
ans=ans*ans%MOD;
if((p&1)==1) ans=(a%MOD*ans)%MOD;
return ans;
}
int e,first[40010],__next[40010],v[40010];
void AddEdge(int U,int V){
v[++e]=V;
__next[e]=first[U];
first[U]=e;
}
int T,n,m,fa[40010];
int siz[40010];
void dfs(int U){
siz[U]=1;
for(int i=first[U];i;i=__next[i]){
dfs(v[i]);
siz[U]+=siz[v[i]];
}
}
int main(){
// freopen("uva11174.in","r",stdin);
int x,y;
scanf("%d",&T);
for(;T;--T){
memset(fa,0,sizeof(fa));
memset(first,0,sizeof(first));
e=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
AddEdge(y,x);
fa[x]=y;
}
for(int i=1;i<=n;++i){
if(!fa[i]){
AddEdge(n+1,i);
}
}
dfs(n+1);
ll t=1;
for(int i=1;i<=n;++i){
t=(t*(ll)siz[i])%MOD;
}
ll t2=1;
for(int i=1;i<=n;++i){
t2=(t2*(ll)i)%MOD;
}
printf("%d\n",(int)((t2*Quick_Pow(t,MOD-2))%MOD));
}
return 0;
}
【递推】【推导】【乘法逆元】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 1436 Counting heaps —— (组合数的好题)
这两个题的模型是有n个人,有若干的关系表示谁是谁的父亲,让他们进行排队,且父亲必须排在儿子前面(不一定相邻).求排列数. 我们假设s[i]是i这个节点,他们一家子的总个数(或者换句话说,等于他的子孙数 ...
- 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 (组合+除法的求模)
题意:村子里有n个人,给出父亲和儿子的关系,有多少种方式可以把他们排成一列,使得没人会排在他父亲的前面 思路:设f[i]表示以i为根的子树有f[i]种排法,节点i的各个子树的根节点,即它的儿子为c1, ...
- UVA 11174 Stand in a Line 树dp+算
主题链接:点击打开链接 题意:白书的P103. 加个虚根就能够了...然后就是一个多重集排列. import java.io.PrintWriter; import java.util.ArrayLi ...
- [LOJ3086][GXOI/GZOI2019]逼死强迫症——递推+矩阵乘法
题目链接: [GXOI/GZOI2019]逼死强迫症 设$f[i][j]$表示前$i$列有$j$个$1*1$的格子的方案数,那么可以列出递推式子: $f[i][0]=f[i-1][0]+f[i-2][ ...
- 递推+高精度+找规律 UVA 10254 The Priest Mathematician
题目传送门 /* 题意:汉诺塔问题变形,多了第四个盘子可以放前k个塔,然后n-k个是经典的汉诺塔问题,问最少操作次数 递推+高精度+找规律:f[k]表示前k放在第四个盘子,g[n-k]表示经典三个盘子 ...
- 数学:UVAoj 11174 Stand in a Line
Problem J Stand in a Line Input: Standard Input Output: Standard Output All the people in the bytela ...
随机推荐
- 空间数据库系列二:空间索引S2与Z3分析对比
S2与Z3对比分析 1. S2 2. Geohash 3. Geomesa Z3 4. S2对比geohash 4.1. geohash存在的问题 4.2. S2优势 4.3. 实际对比例子 5. 测 ...
- /proc/diskstats文件注解
/proc/diskstats 注解 今儿在准备利用shell监控磁盘读写次数等信息时,看到该文件,但是又不清楚每段的具体含义,这里备注下. 文件内容 [root@namenode proc]# ca ...
- Vue组件-组件的属性
在html中使用元素,会有一些属性,如class,id,还可以绑定事件,自定义组件也是可以的.当在一个组件中,使用了其他自定义组件时,就会利用子组件的属性和事件来和父组件进行数据交流. 比如,子组件需 ...
- centos 快捷键
centos 快捷键大全 时间:2013-02-23 14:54来源:blog.csdn.net 举报 点击:225次 新手通常会不太习惯GNOME或KDE的界面操作,不过还好,LINUX的快捷键大多 ...
- centos_7.1.1503_src_7
http://vault.centos.org/7.1.1503/os/Source/SPackages/ tex-fonts-hebrew-0.1-21.el7.src.rpm 05-Jul-201 ...
- 1003: FFF团的情侣活动--课程作业--找出N个数字中唯一出现奇数次的数
1003: FFF团的情侣活动 Time Limit: 1 Sec Memory Limit: 2 MB Description 圣诞节快到了,Water作为大FFF团团长,组织许多对情侣进行电影院 ...
- Python简单的制作图片验证码
-人人可以学Python--这里示范的验证码都是简单的,你也可以把字符扭曲 人人可以学Python.png Python第三方库无比强大,PIL 是python的一个d第三方图片处理模块,我们也可以使 ...
- Leetcode 之Longest Common Prefix(33)
在一组字符串中找到最长的子串.采用纵向匹配,遇到第一个不匹配的停止. string longestComPrefix(vector<string> &strs) { if (str ...
- Mac下 Docker部署SpringBoot应用
一.安装Docker环境 使用 Homebrew 安装 macOS 我们可以使用 Homebrew 来安装 Docker. Homebrew 的 Cask 已经支持 Docker for Mac,因此 ...
- 《java并发编程实战》读书笔记8--死锁,性能与可伸缩性,锁粒度锁分解锁分段
第10章 避免活跃性危险 10.1 死锁 -10.1.1 锁顺序死锁 最简单的一种死锁形式: -10.1.2 动态的锁顺序死锁 可以通过下面的方法来解决: -10.1.3 在协作对象之间发生死锁 -1 ...