小W与网格

lucas定理 http://www.cnblogs.com/vongang/archive/2012/12/02/2798138.html

题目:http://hihocoder.com/contest/challenge13/problem/1

彬神的方法……

假设右上方向出格子 右上方向 宽 为 w ,高 为 h,

则从 上方的格子出去可以走 0 个 横向,1 个 横向 … 到 w 个 横向,

但是所走的  是  在 那个 位置 走 那几个 横向,是从 n 个 盒子 里 放 m 个 球的问题

放球问题 http://baike.baidu.com/link?url=DScWeVQGjvSW6VRzRw0tPXg9q9bbCBEBK7fk_pCZHA5LGIKccTp0eWjFzcPVf_lSnemIXCmNdnxOmUIsO2Ddka

同理 从右边的格子出去可以走  0 个高度,1个高度……到 h 个高度

 

其中 n ,m 为 1 要特殊处理

由于 四个方向计算了两次 ,所以要 - 4

 

贴代码……

#include <iostream>

#include <cstring>

#include <cstdio>

#include <cmath>

#include <algorithm>

#include <vector>

#include <map>

#include <queue>

#include <stack>

#include <set>

#include <string>

using namespace std;

typedef long long ll;

const double ESP = 10e-8;

const int MOD = 1000000007;

typedef long long LL;

LL exp_mod(LL a, LL b, LL p) {

    LL res = 1;

    while(b != 0) {

        if(b&1) res = (res * a) % p;

        a = (a*a) % p;

        b >>= 1;

    }

    return res;

}



LL Comb(LL a, LL b, LL p) {

    if(a < b)   return 0;

    if(a == b)  return 1;

    if(b > a - b)   b = a - b;



    LL ans = 1, ca = 1, cb = 1;

    for(LL i = 0; i < b; ++i) {

        ca = (ca * (a - i))%p;

        cb = (cb * (b - i))%p;

    }

    ans = (ca*exp_mod(cb, p - 2, p)) % p;

    return ans;

}



LL Lucas(int n, int m, int p) {

     LL ans = 1;



     while(n&&m&&ans) {

        ans = (ans*Comb(n%p, m%p, p)) % p;

        n /= p;

        m /= p;

     }

     return ans;

}

int fun(int h,int w){

    int ans = 0;

    for(int i = 0;i <= h;i++){

        ans += Lucas(w+i,i,MOD);

        ans %= MOD;

    }

    for(int i = 0;i < w;i++){

        ans += Lucas(h+i,i,MOD);

        ans %= MOD;

    }

    return ans;

}

int main(){

//    freopen("input.txt","r",stdin);

    int n,m,i,j;

    while(~scanf("%d%d%d%d",&n,&m,&i,&j)){

        if(n==1){

            printf("%d\n",m);

            continue;

        }else if(m==1){

            printf("%d\n",n);

            continue;

        }

        int ans = fun(i-1,j-1);

        ans += fun(n-i,j-1);

        ans %= MOD;

        ans += fun(i-1,m-j);

        ans %= MOD;

        ans += fun(n-i,m-j);

        ans %= MOD;

        ans = (ans-4+MOD)%MOD;

        printf("%d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(小W与网格)