邪教喜欢在各种各样空间内跳。

现在,邪教来到了一个二维平面。在这个平面内,如果邪教当前跳到了(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。

思路:这个题贪心的思路应该比叫好想,因为,越往第一象限深处走,花费的体力越多,所以我们肯定要尽可能多的在坐标轴上走,尽可能少的在象限里走,这样路线就出来了。。。
关键是如何求这个路线,首先第一部分肯定是max(m,n),然后观察可以发现象限里的每一个点都等于c(x+y,x),这样第二部分的答案就应该是:c(max(m,n)+0,0)+c(max(m,n)+1,1)+c(max(m,n)+2,2)+c(max(m,n)+3,3)+……+c(max(m,n)+min(m,n),min(m,n);
根据组合数的的一些性质上式可以合并为c(m+n+1,min(m,n));
这样我们的答案就变成了max(m,n)+c(m+n+1,min(m,n));(%1000000007);
但是m,n特别大,而且是除法,所以再用费马小定理求个乘法逆元搞一搞就好了。。。

#include<iostream>
using namespace std;
long long m,n,haha,a,b,x,y,temp,temp1,c(1000000007),ans,p,ans2;;
long long zuhe(long long a, long long b)
{
      ans=1;
      p=1;
      for (long long i=a;i>=max(b,a-b)+1;i--)
        ans=(ans*(i%c))%c;
      for (long long i=1;i<=min(b,a-b);i++)
        p=(p*(i%c))%c;
      x=p%c;
      y=c-2;
      ans2=1;
      while (y>0)
       {
         if (y%2==1)
           ans2=(ans2*x)%c;
         y/=2;
         x=(x*x)%c;
       }
      ans=(ans*ans2)%c;
      return ans;
}
int main()
{
    cin>>m>>n;
    haha=max(m,n)%c;
    a=m+n+1;
    b=min(m,n);
    haha=(haha+zuhe(a,b))%c;
    cout<<haha;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值