zoukankan      html  css  js  c++  java
  • [BZOJ 3260] 跳

    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,表示邪教想到达的点。 
     

    Output

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

    Sample Input


    1 2

    Sample Output

    6

    HINT

     

    对于 100% 的数据,满足    0<=N, M<=10^12   ,N*M<=10^12。

    题解:Lucas定理+贪心

    先打出个表来,发现c数组就是杨辉三角嘛(只不过45°的放在数组里。

    然后(x,y)的C值,就是组合数C(x+y,y)。

    那么对于点n,m,先沿着(0,0)-->(1,0)-->(2.0)--...-->(n,0)

    然后(n,1)-->(n,2)-->(n,3)--...(n,m),表上看出C(n,m)=C(m,n),(这个C是价值

    然后用Lucas求组合数就可以啦。

    其实本来想做费马小定理来着...

    在Lucas求逆元中,n!/(m!*(n-m)!)==> n!*(m!*(n-m)在mod数意义下的逆元)

    由欧拉定理知道a^(phi(n))≡1(mod n)当a,n互质时,费马小定理为当n为质数时

    a^(phi(n))=a^(n-1)≡1(mod n),那么a关于MOD n意义下的逆元就是a^(n-2)。

    假设n>m(让竖着走的1多一点

    那么答案就是n+sigma(i=0--m)C(n+i,i)

    sigma那个是  C(n+m+1,m)。

    这个我不会证.....才怪 略略略

    证明:C(n,0)+C(n+1,1)+C(n+2,2)+C(n+2,3)+....+C(n+m,m)

    额...不会 推荐播客

    代码:

    最近Lucas定理做的太多了...不做了.... 感觉这个题的数据范围有点玄....

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define LL long long
    using namespace std;
    const LL mod=1e9+7;
    
    LL m,n;
    
    LL ksm(LL x,LL y){
        LL ret=1;
        while(y){
            if(y&1)ret=ret*x%mod;
            x=x*x%mod;
            y>>=1;
        }
        return ret;
    }
    
    LL C(LL n,LL m){
        if(m>n)return 0;
        LL s1=1,s2=1;
        for(LL i=n-m+1;i<=n;i++)s1=s1*i%mod;
        for(LL i=1;i<=m;i++)s2=s2*i%mod;
        return s1*ksm(s2,mod-2);
    }
    
    LL Lucas(LL n,LL m){
        if(!m)return 1;
        return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod; 
    }
    
    int main(){
        scanf("%lld%lld",&n,&m);
        printf("%lld
    ",(max(n,m)%mod+Lucas(n+m+1,min(n,m))%mod)%mod);
        return 0;
    }
  • 相关阅读:
    数据结构与算法—栈和队列
    数据结构与算法—双向链表
    数据结构与算法—单向循环链表
    hashMap高低位异或原理
    MySQL中order by排序时,数据存在null,排序在最前面
    Class.getSimpleName()的作用
    Linux密码过期问题,即WARNING:Your password has expired
    CSS

    easyexcel注解
  • 原文地址:https://www.cnblogs.com/zzyh/p/7669966.html
Copyright © 2011-2022 走看看