uva 11174 - Stand in a Line(逆元+递推)

题目连接:uva 11174 - Stand in a Line

题目大意:村子里有n个村名民,现在他们要排成一列,处于对长辈的尊敬,他们不能排在自己父亲的前面,有些人的父亲不一定在村子了。问有多少种列的顺序。

解题思路:【算法竞赛入门经典-训练指南】的例题,主要还用到了欧几里得拓展定理求逆元。

#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;
typedef long long ll;
const int N = 40005;
const ll MOD = 1e9+7;

int n, m;
ll v[N];
vector<int> g[N];

void init () {
    scanf("%d%d", &n, &m);

    memset(v, 0, sizeof(v));
    for (int i = 0; i <= n; i++)
        g[i].clear();

    int a, b;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &a, &b);
        g[b].push_back(a);
    }
}

ll dfs(int x) {
    if (v[x])
        return v[x];

    for (int i = 0; i < g[x].size(); i++)
        v[x] += dfs(g[x][i]);
    return ++v[x];
}

void gcd (ll a, ll b, ll& x, ll& y, ll& d) {
    if (b == 0) {
        d = a;
        x = 1;
        y = 0;
    } else {
        gcd(b, a%b, y, x, d);
        y -= x*(a/b);
    }
}

int main () {
    int cas;
    scanf("%d", &cas);
    while (cas--) {
        init ();

        ll ans = 1, b = 1;
        for (ll i = 1; i <= n; i++)
            ans = (ans * i) % MOD;

        for (int i = 1; i <= n; i++)
            b = (b * dfs(i)) % MOD;

        ll p, k, d = 1;
        gcd(b, MOD, p, k, d);
        ans = ((ans * p) % MOD + MOD) % MOD;
        printf("%lld\n", ans);
    }
    return 0;
}

uva 11174 - Stand in a Line(逆元+递推)

时间: 2024-10-05 22:31:54

uva 11174 - Stand in a Line(逆元+递推)的相关文章

【递推】【推导】【乘法逆元】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)

UVa 11174 Stand in a Line

依旧是<训练指南>上的一道例题.书上讲的比较抽象,下面就把解法具体一下.因为涉及到父子关系,因此自然而然可以将n个节点构造成一棵树,最后将形成一个森林.接下来将使用递归的手法.设f(i)是以节点i为树根的子树,节点i有儿子c1,c2,c3....cj共j棵子树.s[i]为树根为i的子树包含的节点数.如果分别先给各个子树内部排序,那么毫无疑问, 共有f(c1)*f(c2)*f(c3)....*f(cj)种情况.接下来又要将所有子树的节点排成一个序列.那么我们事先不考虑各个子树的内部排序,共有(s

UVA 11174 Stand in a Line 树形dp+计数

题目链接:点击打开链接 题意:白书的P103. 加个虚根就可以了...然后就是一个多重集排列. import java.io.PrintWriter; import java.util.ArrayList; import java.util.Scanner; public class Main { static int N = 40100; ArrayList<Integer>[] G = new ArrayList[N]; static long mod = 1000000007; long

UVA 1073 - Glenbow Museum(数论+计数问题+递推)

题目链接:1073 - Glenbow Museum 白书上的例题,需要一定的推理. 首先要把问题转化,推理出n个点,R的个数为(n + 4) / 2, O的个数为(n - 4) / 2个,因为首先四个角必须为R,然后在中间添加O点,每有一个O点就要多一个R点,所以最后R点比O点多4. 然后问题就转化为给定n个R点和m个O点,求出有多少个序列,要求O点不连续,并且R的连续个数不能超过4,的序列个数. 可以设状态dp[i][j][2][2],表示用到第i个R点第j个O点,开头点,结尾点,的情况种数

UVA 10253 - Series-Parallel Networks(数论+计数问题+递推)

题目链接:10253 - Series-Parallel Networks 白书的例题. 这题也是需要把问题进行转化,一个并联可以分为几个串联,然后串联可以分成边. 如此一来,最后叶子结点种数会是n,问题转化为去分配叶子结点,使得总和为n. 书上有两种方法,一种直接去递归,利用组合数学的方式去计算答案. 一种是推出递推式: 设dp[i][j]为一共j个叶子结点的树,子树的叶子最多的为i个的情况.然后对于一颗树,枚举恰好包含i个叶子的子树为p棵,那么相当于从f[i]颗树中选出p棵树的方案数,是可重

UVA 10910 Marks Distribution(组合数学 或 递推)

Marks Distribution Time limit: 3.000 seconds In an examination one student appeared in N subjects and has got total T marks. He has passed in all the Nsubjects where minimum mark for passing in each subject is P. You have to calculate the number of w

UVA 550 Multiplying by Rotation (简单递推)

题意:有些数字是可以这样的:abcd*k=dabc,例如179487 * 4 = 717948,仅仅将尾数7移动到前面,其他都不用改变位置及大小.这里会给出3个数字b.d.k,分别代表b进制.尾数.第2个乘数.既然是尾数,必有d<b.求这个abc...d一共有几位数(按b进制算). 思路:举例,进制是十,假设这个数字是6位的,那么abcdef代表了这6位数,f已经给出,是7,且另个乘数是4.因为abcde7*4=7abcde. (1)推e : 4*7=28,那么e一定是为8. (2)推d:abc

UVa 10328 Coin Toss(Java大数+递推)

https://vjudge.net/problem/UVA-10328 题意: 有H和T两个字符,现在要排成n位的字符串,求至少有k个字符连续的方案数. 思路:这道题目和ZOJ3747是差不多的,具体做法可以参考另一篇博客http://www.cnblogs.com/zyb993963526/p/7203833.html 但是这道题目的话是要用大数来做的,c++感觉不太好写,就学了下java的做法. 1 import java.math.BigInteger; 2 import java.ut

UVa 10943 How do you add?【递推】

题意:给出n,k,问恰好有k个不超过n的数的和为n的方案数有多少 可以隔板法来做 现在有n个小球放到k个盒子里面,盒子可以为空 那么就是n-k+1个缝隙,放上k-1个隔板(k-1个隔板就分成了k份) 所以总的方案数为 C(n+k-1,k-1) 所以可以转化为C(i,j)=C(i-1,j)+C(i,j-1) 即为d[i][j]=d[i-1][j]+d[i][j-1], d[i][j]表示j个数的和恰为i的方案数 1 #include<iostream> 2 #include<cstdio&