转:这题里介绍的最短路比较特殊,,这条最短路要遍历全图一遍,我们可以枚举最短路径,而组成最短路径需要N-1条边,一共有(N-2)!条可行的最短路径。
如果已经确定了最短路,我们肯定不会加入“捷径边”,就是让最短路有可能变短的边,一共有条。
于是我们可以把剩下的M-(N-1)条边可以选择成为N*N-种有向边中的一种。于是我们可以使用经典的挡板问题组合:
把N个相同的元素放进M个桶的方案数为
推得答案就是这个组c vxxv合数可以使用杨辉三角推出(期望得分60%),也可以使用逆元推m-(n-1)次。最后再乘以(n-2)!,就是答案了。时间复杂度为O(MlogN+N)可以通过全部数据。期望得分100%
#include<bits/stdc++.h>
#define N 100010
#define P 50010
#define inf 2147483647
#define rint register ll
#define ll long long
#define mod (ll)(1e9+7)
#define mem(a,b) memset(a,b,sizeof (a))
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
ll ans,n,m;
ll a,b,c,f[N],finv[N];
ll sqr(ll x)
{ return x*x%mod;}
ll power(ll x,ll p)
{
if(p==0)return 1;
if(p&1) return x*sqr(power(x,p/2))%mod; else return sqr(power(x,p/2))%mod;
}
ll inv (ll x)
{return power(x%mod,mod-2);}
ll fact(ll x)
{
ll ans=1;
for(rint i=1;i<=x;i++)ans=ans*i%mod;
return ans;
}
ll C(ll n,ll m)
{
ll a=1,b=0;
for(rint i=m+1;i<=n;i++)a=a*i%mod;
b= fact(n-m) %mod;
return a*inv(b)%mod;
}
ll db(ll n,ll m)//n分成m份的方案数
{
return C(n+m-1 , m);
}
int main()
{
open("pg");
scanf("%lld%lld",&n,&m);
ans= db(n*n - (n-1)*(n-2)/2 , m-(n-1)) * fact(n-2) %mod;
printf("%lld",ans);
}