[bzoj3260][数论]跳

63 篇文章 0 订阅

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

读入两个整数 N ,M,表示邪教想到达的点。 0<=N, M<=10^12 ,N*M<=10^12

Output

输出仅一个整数,表示邪教需要花费的最小体力对 10^9+7取模的结果。

Sample Input

1 2

Sample Output

6

题解

画了一个表后发现这是个45度摆着的杨辉三角??
大胆猜一手结论,横着走到底然后竖着走到终点。
把表画出来后你可以发现,对于(n,m),我们保证n>m的情况下,竖着走的那一条其实就是从(n,1)走到(n,m)。然后你又会发现,这一段的和是等于(n+1,m)的。
于是就转化为求杨辉三角内任意一个点的权了??
在杨辉三角内第i行第j个数,其权为 C(i1,j1) C ( i − 1 , j − 1 ) ,其中i-1在下j-1在上
再画一下可以发现(n+1,m)在杨辉三角内的位置是(n+m+2,m+1),于是公式就有 C(n+m+1,m) C ( n + m + 1 , m )
化成阶乘的形式可以变成
(n+m+1)!/(m!(n+1)!) ( n + m + 1 ) ! / ( m ! ∗ ( n + 1 ) ! )
(n+1)! ( n + 1 ) ! 除去之后可以得到
(n+2)(n+3)...(n+m+1)/m! ( n + 2 ) ∗ ( n + 3 ) ∗ . . . ∗ ( n + m + 1 ) / m !
上面有m项,下面也有m项,复杂度是O(m)的。题目里有一个条件n*m<=10^12,且我们保证了m< n,那么m最大也就10^6,完全过得去
把分母的值求出来后求个逆元搞一下就可以了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
LL pow_mod(LL a,int b)
{
    LL ans=1;
    while(b)
    {
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;b>>=1;
    }
    return ans;
}
LL n,m;
int main()
{
    scanf("%lld%lld",&n,&m);
    if(n<m)swap(n,m);n%=mod;
    LL tmp=1;
    for(int i=1;i<=m;i++)tmp=tmp*i%mod;
    tmp=pow_mod(tmp,mod-2);
    for(int i=n+2;i<=n+m+1;i++)tmp=tmp*i%mod;
    printf("%lld\n",(n+tmp)%mod);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值