zoukankan      html  css  js  c++  java
  • JZOJ 3085. 图的计数

    题目

    Description

    在观察完第一个作业之后你终于开始观察第二个作业了,第二个作业十分无聊,就只是一道题目。


    询问有多少个N个点,M条边的有向图,从1号点到达N号点需要经过至少N-1条边。该有向图中可以包含重边和自环。


     

    Input

    第一行两个整数N,M


    Output

    仅一个整数表示答案 mod (10^9+7)。


     

    Sample Input

    2 2

    Sample Output

    4
     

    Data Constraint

     
     

    Hint

    对于30%的数据 N<=5,M<=10


    对于60%的数据 N<=80,M<=3000


    对于100%的数据 1<=N<=10000  1<=M<=100000

     

     

    分析

     

    • 首先,我们可以看到在这个n个点m条边的有向图中,最短路径是n-1
    • 那么我们已经确定了n-1条边,剩下的边肯定不能使最短路径变得更短
    • 简单点来说,就是剩下的边不能在n-1最短路径上的边里两两连边,这样的话方案数就很容易算出来了,C(n-1,2)=(n-1)(n-2)/2
    • 那么我们就可以把剩下的m-n+1条边随便放入图中,那么就有N*N-C(n-1,2)的一种情况
    • 就相当与把n个球放入m个挡板中C(n-m+1,n)
    • 答案就是C(n*n-C(n-1,2)-1+m-(n-1),m-(n-1))
    • 使用逆元推 m-(n-1)次。最后再乘以(n-2)!,就是答案了。时间复杂度为 O(MlogN+N) 

     

    代码

    #include<cstdio>
    const int md=1000000007;
    long long n,m;
    long long qsm(long long x,long long t){
        long long s=1;
        while (t>0){
            if (t%2==1) s=s*x%md;
            x=x*x%md;
            t=t/2;
        }
        return s;
    }
    long long g(long long b,long long d){
        long long v=1;
        for (int i=1;i<=d;i++)v=(b-i+1)*v%md*qsm(i,md-2)%md;
        for (int i=1;i<=n-2;i++)v=v*i%md;
        return v;
    }
    int main(){
        scanf("%lld%lld",&n,&m);
        printf("%lld",g(n*n-(n-1)*(n-2)/2+m-n,m-n+1));
        return 0;
    }

     

    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    奔跑的绵羊js
    13.差分
    12.子矩阵的和
    11.前缀和
    10.高精度除法
    9.高精度乘法
    8.高精度减法
    7.高精度加法
    6.数的三次方根
    5.数的范围
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/10312508.html
Copyright © 2011-2022 走看看