[数学] Jzoj P3085 图的计数

 

Description

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


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


 

 
Input

第一行两个整数N,M


 

Output

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


 

 
Sample Input
2 2
Sample Output
4
 
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))
  • 最后的话,答案还要乘上(n-2)!

代码

 1 #include <cstdio>
 2 #define ll long long
 3 using namespace std;
 4 ll n,m,ans=1,mx,j,f,x,y,z,r,mo=1e9+7;
 5 ll ksm(ll a,ll b){ for (r=1;b;b>>=1,a=a*a%mo) if (b&1) r=r*a%mo; return r; }
 6 int main()
 7 {
 8     scanf("%lld%lld",&n,&m);
 9     if (m<n-1) { printf("0\n"); return 0; }
10     for (ll i=1;i<=n-2;i++) ans=ans*i%mo;
11     mx=(n+n-1+((n-1)*n)/2%mo)%mo,m-=n-1,f=1;
12     for (ll i=1;i<=mx-1+m;i++,f=f*i%mo)
13         if (i==mx-1+m) x=f;
14         else if (i==mx-1) y=f;
15         else if (i==m) z=f;
16     ans=ans*x%mo*ksm(y,mo-2)%mo*ksm(z,mo-2)%mo,printf("%lld\n",ans);
17 }

 

转载于:https://www.cnblogs.com/Comfortable/p/10309878.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值