正题
题目大意
求有多少个m条边的有向图使得1到n的最短路长度为n-1
解题思路
首先长度为n−1n-1n−1那么就是1到n得先是一条链。在链上加m−n+1m-n+1m−n+1条边且不能加如捷径边。
捷径边的条数为Cn−12C_{n-1}^2Cn−12,然后可以加的边数就是n∗n−Cn−12n*n-C_{n-1}^2n∗n−Cn−12。但是考虑到有重边的情况,考虑用隔板法求。
将n∗n−Cn−12n*n-C_{n-1}^2n∗n−Cn−12物品放入m−n+1m-n+1m−n+1个桶里,对于每张图就是加入桶里的第一条边,重边数量为桶中的物品数量。
然后因为2∼n−12\sim n-12∼n−1的点可以进行排列,所以答案要再乘上一个(n−2)!(n-2)!(n−2)!
组合数用逆元求可过。
codecodecode
#include<cstdio>
#define ll long long
using namespace std;
const ll XJQ=1e9+7;
ll n,m,j[10010],z;
ll power(ll x,ll b)
{ll ans=1;x%=XJQ;while(b){if(b&1) ans=ans*x%XJQ;x=x*x%XJQ;b>>=1;}return ans;
}
ll C(ll n,ll m)
{ll ans1=1,ans2=1;for(ll i=n-m+1;i<=n;i++)ans2=ans2*i%XJQ;for(ll i=1;i<=m;i++)ans1=ans1*power(i,XJQ-2)%XJQ;return ans2*ans1%XJQ;
}
int main()
{scanf("%lld%lld",&n,&m);j[0]=1;for(ll i=1;i<=n-2;i++)j[i]=j[i-1]*i%XJQ;printf("%lld",C((n*n-C(n-1,2)-1+m-n+1),m-n+1)*j[n-2]%XJQ);
}