题意:

     有n个人要排队,给你一些父子关系,要求儿子不能站在自己的父亲前面,问有多少种排队方式?

思路:

      白书上的题目,首先我们可以把关系建成树,这样我们就有可能得到一个森林(或者是一课树),然后我们再虚拟出来一个点0连接所有森林的根节点,这样是为了保证是一棵树,然后题目就变成了给你一棵树,不改变关系,问这个树有多少种方式,这个还是排列组合问题,对于每一个根节点,有这样的性质

root[i] = f[1]*f[2]*..f[k]   *  (s[i]-1)!/s[1]!*s[2]!*..s[k]! 

f[1]..f[k]表示的当前根节点连接的k个儿子为根节点的树的排列个数,s[i]表示的是以i为根节点的这棵树的所有节点个数,上面的式子可以理解成这样

f[1]*f[2]*..f[k] 所有儿子为根节点的排列个数

(s[i] - 1)! 表示的是以i为根的这棵树的所有节点数-1(不算跟所以-1)的排列方式

//s[1]!*s[2]!*..s[k]!  相当于全排列去掉重复部分,因为每一棵树已经*f[]了,不能在*了,不能再*那就可以理解成重复部分了,所以...,然后把每一个公式都化简,会发现分子剩1,分母剩s[i]了,(可以理解成分子的f[i]和分母的s[i]!约),这样最后剩下的是

((n+1)-1)/s1*s2*..sn;

最后的公式是

Ans = n!/(s1*s2*s3*s4...*sn) si是以i为根节点的子树的节点数

这样就可以了,然后这样会设计到一个问题,那就是大数相除取余的问题,我知道应该有至少两种方法解决这个问题,一个是逆元,另一个是a/b%c = a * pow(b ,c - 2) % c,这个不解释了,可以自己去网上找学习,哎!想起了亚洲赛那道排列组合题,当时在赛场上怎么也想不起来大数相除的转换了,sb了!

#include<stdio.h>

#include<string.h>

#define MOD 1000000007

#define N_node 40000 + 10

#define N_edge 40000 + 10

typedef struct

{

   int to ,next;

}STAR;

STAR E[N_node];

long long sum[N_node];

long long jc[N_node];

int list[N_node] ,tot;

int du[N_node];

void add(int a ,int b)

{

   E[++tot].to = b;

   E[tot].next = list[a];

   list[a] = tot;

}

int DFS(int now)

{

   int s = 1;

   for(int k = list[now] ;k ;k = E[k].next)

   {

      s += DFS(E[k].to);

   }

   sum[now] = s;

   return s;

}

long long Pow(long long a ,long long b)

{

   long long c = 1;

   while(b)

   {

      if(b & 1) c *= a;

      b >>= 1;

      a *= a;

      a = a % MOD;

      c = c % MOD;

   }

   return c;

}

void DB()

{

   long long now = 1;

   for(long long i = 1 ;i <= 40000 ;i ++)

   {

      now = now * i % MOD;

      jc[i] = now;

   }

}

   

int main ()

{

   int n ,m ,i ,a ,b ,t;

   DB();

   scanf("%d" ,&t);

   while(t--)

   {

      scanf("%d %d" ,&n ,&m);

      memset(list ,0 ,sizeof(list)) ,tot = 1;

      memset(du ,0 ,sizeof(du));

      for(i = 1 ;i <= m ;i ++)

      {

         scanf("%d %d" ,&a ,&b);

         add(b ,a);

         du[a] ++;

      }

      for(i = 1 ;i <= n ;i ++)

      if(!du[i]) add(0 ,i);

      memset(sum ,0 ,sizeof(sum));

      DFS(0);

      long long Ans = jc[n];

      for(i = 1 ;i <= n ;i ++)

      {

          Ans = Ans * Pow(sum[i] ,MOD - 2) % MOD;

      }

      printf("%lld\n" ,Ans);

   }

   return 0;

}

      

      

      

   

      

UVA11174村民排队问题的更多相关文章

  1. [uva11174]村民排队 递推+组合数+线性求逆元

    n(n<=40000)个村民排成一列,每个人不能排在自己父亲的前面,有些人的父亲不一定在.问有多少种方案. 父子关系组成一个森林,加一个虚拟根rt,转化成一棵树. 假设f[i]表示以i为根的子树 ...

  2. acdream 1683 村民的怪癖(KMP,经典变形)

    Problem Description 娜娜费劲九牛二虎之力终于把糖果吃完了(说好的吃不完呢?骗人,口亨~),于是,缘溪行,忘路之远近.忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷,娜娜甚异之 ...

  3. POJ 2828 Buy Tickets(排队问题,线段树应用)

    POJ 2828 Buy Tickets(排队问题,线段树应用) ACM 题目地址:POJ 2828 Buy Tickets 题意:  排队买票时候插队.  给出一些数对,分别代表某个人的想要插入的位 ...

  4. D - 娜娜梦游仙境系列——村民的怪癖

    D - 娜娜梦游仙境系列——村民的怪癖 Time Limit: 2000/1000MS (Java/Others)    Memory Limit: 128000/64000KB (Java/Othe ...

  5. Python开发——排队问题随机模拟分析

    案例:主要是基于"蒙特卡罗思想",求解排队等待时间问题 场景:厕所排队问题 1.两场电影结束时间相隔较长,互不影响: 2.每场电影结束之后会有20个人想上厕所: 3.这20个人会在 ...

  6. 银行排队问题之单队列多窗口加VIP服务(30 分)

    银行排队问题之单队列多窗口加VIP服务(30 分) 假设银行有K个窗口提供服务,窗口前设一条黄线,所有顾客按到达时间在黄线后排成一条长龙.当有窗口空闲时,下一位顾客即去该窗口处理事务.当有多个窗口可选 ...

  7. PTA 银行排队问题之单队列多窗口服务(25 分)

    银行排队问题之单队列多窗口服务(25 分) 假设银行有K个窗口提供服务,窗口前设一条黄线,所有顾客按到达时间在黄线后排成一条长龙.当有窗口空闲时,下一位顾客即去该窗口处理事务.当有多个窗口可选择时,假 ...

  8. POJ2182(排队问题)

    Lost Cows Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10695   Accepted: 6865 Descri ...

  9. codevs——2956 排队问题

    2956 排队问题  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 有N个学生去食堂,可教官规定:必须2人或3 ...

随机推荐

  1. 翻译:《实用的Python编程》03_05_Main_module

    目录 | 上一节 (3.4 模块) | 下一节 (3.6 设计讨论) 3.5 主模块 本节介绍主程序(主模块)的概念 主函数 在许多编程语言中,存在一个主函数或者主方法的概念. // c / c++ ...

  2. 话说CAS

    一.前言 cas 一般认为是compare and swap 也可以认为是compare and set cas涉及三个值 1)P 变量内存地址 2)E 期望值 ,CPU做计算之前拿出来的旧值 3) ...

  3. MyBatis(八):MyBatis插件机制详解

    MyBatis插件插件机制简介 ​ MyBatis插件其实就是为使用者提供的自行拓展拦截器,主要是为了可以更好的满足业务需要. ​ 在MyBatis中提供了四大核心组件对数据库进行处理,分别是Exec ...

  4. 你想知道的 std::vector::push_back 和 std::vector::emplace_back

    引言 C++ 11 后,标准库容器 std::vector 包含了成员函数 emplace 和 emplace_back.emplace 在容器指定位置插入元素,emplace_back 在容器末尾添 ...

  5. (数据科学学习手札112)Python+Dash快速web应用开发——表单控件篇(上)

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 这是我的系列教程Python+Dash快速web ...

  6. Nodejs学习笔记(5) 文件上传系统实例

    目录 2018.8.4更新:  MySQL可以存放几乎任何类型的数据(图片.文档.压缩包等),但这不是最好的解决方案,正常情况下都是在数据库中存放文件路径,图片.音乐.视频.压缩包.文档等文件存放在硬 ...

  7. 10、字典dict

    字典(dict) 字典是有序,键不重复,元素只能是键值对的可变的容器 dict = {'k1':'v1','k2':'v2'} 容器 元素必须键值对 键不重复,重复则会被覆盖 data = {'k1' ...

  8. python 实现输出一个等腰三角形

    这个问题实际上是一个数学问题,我们主要找出每行的规律就可以根据规律来书写代码 """ 2 代码实现输出一个等腰三角形,实际上就是一个等差数列求各项的一个数学> 问题 ...

  9. POJ2635(数论+欧拉筛+大数除法)

    题目链接:https://vjudge.net/problem/POJ-2635 题意:给定一个由两个质数积的大数M和一个数L,问大数M的其中较小的质数是否小于L. 题解:因为大数M已经超过long ...

  10. 利用matplotlib和cmaps根据已有的colormap,重新定义colormap

    算法网上这哥们总结的还可以[1] ,但是使用matplotlib自定义colormap自己掌握的还不够,写在这里 希望达到的目标 使用什么样的颜色,可以自己定义 方便的调用其他人的色标, 使用一部分c ...