关闭

跳[Codevs1515]

标签: 数学
224人阅读 评论(0) 收藏 举报
分类:

题目描述 Description

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

现在,邪教来到了一个二维平面。在这个平面内,如果邪教当前跳到了 (x,y) ,那么他下一步可以选择跳到以下 4 个点: (x1,y),(x+1,y),(x,y1),(x,y+1)

而每当邪教到达一个点,他需要耗费一些体力,假设到达 (x,y) 需要耗费的体力用 C(x,y) 表示。

对于 C(x,y) ,有以下几个性质:

1、若 x=0 或者 y=0 ,则 C(x,y)=1

2、若 x>0y>0 ,则 C(x,y)=C(x,y1)+C(x1,y)

3、若 x<0y<0 ,则 C(x,y)=+

现在,邪教想知道从 (0,0) 出发到 (N,M) ,最少花费多少体力(到达 (0,0) 点花费的体力也需要被算入)。

由于答案可能很大,只需要输出答案对 109+7 取模的结果。


输入描述 Input Description

读入两个整数 NM ,表示邪教想到达的点。


输出描述 Output Description

输出仅一个整数,表示邪教需要花费的最小体力对 109+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<=1012NM<=1012


分析

这里写图片描述

上图是 C(x,y)0<xy<12 的部分,从这里我们惊喜地看出 C(x,y)=Cyx+y

题目要求的最小值显然是走直线(如图中阴影部分的最短路径为 1111410 ),证明略。如果令 N>=M ,则走过的点为 (0,0)(1,0)(2,0)...(n,0)(n,1)(n,2)...(n,m) ,则花费为 n1i=0C0i+ni=0Cin = n+Cmn+m+1.
d=109+7 ,故 ans=(n+Cdn+m+1)%m=n%d+mi=1(n+m+2i)mi=1i%d,设 a=mi=1(n+m+2i)b=mi=1ib0b1mod d ,则 ans=n%d+ab%d=n%d+ab0bb0%d=n%d+ab0%d
至于求 b0,因为 bb01(mod d)=kd+1,最后用拓展欧几里得求出 b0 即可


代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;

const LL Mod = 1000000007;

LL n,m;

LL gcd(LL,LL,LL &,LL &);

int main(){

    scanf("%lld%lld",&n,&m);

    if(n<m)
        swap(n,m);

    LL tmp1=1,tmp2=1;
    for(LL i=1;i<=m;++i)
        tmp1 = tmp1*((n+m+2-i)%Mod)%Mod;
    for(LL i=1;i<=m;++i)
        tmp2 = tmp2*i%Mod;


    LL x,y,res;
    res = gcd(tmp2,Mod,x,y);

    printf("%lld",(Mod+n+tmp1*x%Mod)%Mod);

    return 0;
}

LL gcd(LL a,LL b,LL &x,LL &y){

    if(b == 0){
        x = 1;
        y = 0;
        return a;
    }

    LL ans = gcd(b,a%b,x,y);

    LL tmp = x;
    x = y%Mod;
    y = (Mod+tmp-a/b*y)%Mod;

    return ans;

}
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:34942次
    • 积分:1583
    • 等级:
    • 排名:千里之外
    • 原创:128篇
    • 转载:0篇
    • 译文:0篇
    • 评论:5条
    最新评论