[数论][组合数学]HEX

Problem Description

On a plain of hexagonal grid, we define a step as one move from the current grid to the lower/lower-left/lower-right grid. For example, we can move from (1,1) to (2,1), (2,2) or (3,2).

In the following graph we give a demonstrate of how this coordinate system works.

Your task is to calculate how many possible ways can you get to grid(A,B) from gird(1,1), where A and B represent the grid is on the B-th position of the A-th line.

Input

For each test case, two integers A (1<=A<=100000) and B (1<=B<=A) are given in a line, process till the end of file, the number of test cases is around 1200.

Output

For each case output one integer in a line, the number of ways to get to the destination MOD 1000000007.

Sample Input

1 1
3 2
100000 100000

Sample Output

1
3
1

思路:若只能向↙或↘走,从(1,1)->(x,y),总共要走tot=(x-1)步,其中向↘要走r=(y-1)步,向↙要走l=(x-y)步,那么总的走法就是C(tot,r)(或C(tot,l))。
若还能向↓走,因为一步↓相当于一步↙加上一步↘,所以若向↓走i步,总共就只要走tot'=(tot-i)步,向↘走r'=(r-i)步,向↙走l'=(l-i)步,(其中0<=i<=min(l,r)),
那么总的走法数就是C(tot',i)+C(tot'-i,r)(表达形式不止一种)。

AC代码:
#include <iostream>
#include<cstdio>
#include<algorithm>
#define mod 1000000007
#define ll long long
using namespace std;

ll f[100050];
ll revf[100050];

ll qpow(ll x,ll n){
  ll ret=1;
  while(n){
     if(n&1) ret=(ret*x)%mod;
     x=(x*x)%mod;
     n>>=1;
  }
  return ret;
}

ll rev(ll x){
  return qpow(x,mod-2);
}

void init(){//预处理
  f[0]=1; revf[0]=rev(f[0]);
  for(ll i=1;i<=100010;i++){
    f[i]=i*f[i-1]%mod;
    revf[i]=rev(f[i]);
  }
}

ll C(ll n,ll m){
  return f[n]%mod*revf[m]%mod*revf[n-m]%mod;
}

int main()
{
    init();
    ll x,y;
    while(scanf("%lld%lld",&x,&y)!=EOF){
        ll tot_=x-1; ll r_=y-1; ll l_=x-y;
        ll down_max=min(l_,r_);
        ll ans=0;
        for(ll i=0;i<=down_max;i++){
            ll tot=tot_-i; ll l=l_-i; ll r=r_-i;
            ans=(ans+C(tot,i)%mod*C(tot-i,l)%mod)%mod;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2018-04-23 13:17  l..q  阅读(238)  评论(0)    收藏  举报