题目描述 Description
*喜欢在各种各样空间内跳。
现在,*来到了一个二维平面。在这个平面内,如果*当前跳到了(x,y),那么他下一步可以选择跳到以下4个点:(x-1,y), (x+1,y), (x,y-1), (x,y+1)。
而每当*到达一个点,他需要耗费一些体力,假设到达(x,y)需要耗费的体力用C(x,y)表示。
对于C(x,y),有以下几个性质:
1、若x=0或者y=0,则C(x,y)=1。
2、若x>0且y>0,则C(x,y)=C(x,y-1)+C(x-1,y)。
3、若x<0且y<0,则C(x,y)=无穷大。
现在,*想知道从(0,0)出发到(N,M),最少花费多少体力(到达(0,0)点花费的体力也需要被算入)。
由于答案可能很大,只需要输出答案对10^9+7取模的结果。
输入描述 Input Description
读入两个整数N,M,表示*想到达的点。
输出描述 Output Description
输出仅一个整数,表示*需要花费的最小体力对10^9+7取模的结果。
样例输入 Sample Input
1 2
样例输出 Sample Output
6
数据范围及提示 Data Size & Hint
对于10%的数据,满足N, M<=20;
对于30%的数据,满足N, M<=100;
对于60%的数据,满足min(N,M)<=100;
对于100%的数据,满足0<=N, M<=10^12,N*M<=10^12。
首先我们可以发现,格子上的值就是组合数,然后稍微想一下就可以贪心(打表也可以啊)
一直往小的那边走,然后就得到一个min(n,m)*log(10^9+7),log是求乘法逆元,用费马小定理求逆元,这样理论复杂度是可以过的,但是p党没*还要优化一点
其实贪心的路径很好算,有一条都是1,另一条加起来其实就是C(n+m+1,min(n,m))(我是下别人的代码才知道的)
所以答案就是max(n,m)+C(n+m+1,min(n,m))
const
h=;
var
n,m,ans,s:int64; procedure swap(var x,y:int64);
var
t:int64;
begin
t:=x;x:=y;y:=t;
end; function mexp(a,b:int64):int64;
begin
if b= then exit();
mexp:=sqr(mexp(a,b>>))mod h;
if b and = then mexp:=mexp*a mod h;
end; procedure main;
var
i:longint;
begin
read(n,m);
if n>m then swap(n,m);
s:=;
for i:= to n do
s:=s*(((n+m-i+)mod h)*mexp(i,h-)mod h)mod h;
ans:=m+s;
writeln(ans mod h);
end; begin
main;
end.