1515 跳 - Wikioi

题目描述 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))

 1 const

 2     h=1000000007;

 3 var

 4     n,m,ans,s:int64;

 5 

 6 procedure swap(var x,y:int64);

 7 var

 8     t:int64;

 9 begin

10     t:=x;x:=y;y:=t;

11 end;

12 

13 function mexp(a,b:int64):int64;

14 begin

15     if b=0 then exit(1);

16     mexp:=sqr(mexp(a,b>>1))mod h;

17     if b and 1=1 then mexp:=mexp*a mod h;

18 end;

19 

20 procedure main;

21 var

22     i:longint;

23 begin

24     read(n,m);

25     if n>m then swap(n,m);

26     s:=1;

27     for i:=1 to n do

28       s:=s*(((n+m-i+2)mod h)*mexp(i,h-2)mod h)mod h;

29     ans:=m+s;

30     writeln(ans mod h);

31 end;

32 

33 begin

34     main;

35 end.
View Code

 

你可能感兴趣的:(IO)