Description
在观察完第一个作业之后你终于开始观察第二个作业了,第二个作业十分无聊,就只是一道题目。
询问有多少个N个点,M条边的有向图,从1号点到达N号点需要经过至少N-1条边。该有向图中可以包含重边和自环。
Input
第一行两个整数N,M。
Output
仅一个整数表示答案 mod (10^9+7)。
Sample Input
2 2
Sample Output
4
Data Constraint
对于30%的数据 N<=5,M<=10
对于60%的数据 N<=80,M<=3000
对于100%的数据 1<=N<=10000 1<=M<=100000
题解
这题我们看到要求——有向图,n-1条边,可重边+可自环
想到一个可行的方案必定是满足以下几个条件——
1.是一条链且开头为1,结尾为n,中间的是可以打乱顺序的。
2.多出来的边必定是反向边或自环或正向边且距离不超过1。
依照这两个条件我们可以知道
第一个条件贡献的答案为
(
n
−
2
)
!
(n-2)!
(n−2)!
第二个条件下,每条多出来的边的连接方案为——
n
+
(
n
−
1
)
+
n
∗
(
n
−
1
)
/
2
n+(n-1)+n*(n-1)/2
n+(n−1)+n∗(n−1)/2
分别表示该边连接自环、该边正向连接两个点、该边反向连接任意两个点。
这样我们就可以算答案了。
但是要注意,由于每个边的连接方法是等价的,所以第二个条件下的贡献要用组合数来算。
我们把每条多出来的边看做是球,每种连接方案看做是箱子。
于是问题就转化成了给你n个相同球,放入m个不同的箱子里,允许空盒的方案。
这就是一个挡板问题,求解即可。
注意常数!!!
代码
{$inline on}
var
i,j,k,l,n,m:longint;
p,q,answer,x1,x2,x3:int64;
//jc:array[-1..10001] of int64;
mo:int64=1000000007;
function qsm(a,b:int64):int64;inline;
var
t,y:int64;
begin
t:=1;
y:=a;
while b<>0 do
begin
if(b and 1)=1 then
t:=(t*y) mod mo;
y:=(y*y) mod mo;
b:=b shr 1;
end;
exit(t);
end;
begin
readln(n,m);
answer:=1;
for i:=2 to n-2 do
begin
answer:=answer*i mod mo;
end;
q:=n;
p:=q*(q-1) div 2+q+(q-1);//hezi
m:=m-n+1;
x1:=1;
x2:=1;
x3:=1;
for i:=1 to m+p-1 do
begin
if i<=m then x1:=x1*i mod mo;
if i<=p-1 then x2:=x2*i mod mo;
x3:=x3*i mod mo;
end;
answer:=answer*qsm(x1*x2 mod mo,mo-2) mod mo*x3 mod mo;
writeln(answer);
end.
end.