山东 acm D HEX 数学 求组合数

HEX
Time Limit: 4000MS Memory Limit: 131072KB
Submit Statistic
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.
Example Input

1 1
3 2
100000 100000
Example Output

1
3
1
Hint

Author

利用 (1,1)+x*(1,0)+y*(2,1)+z*(1,1)=(a,b).
求得 x+2*y+z=a-1;y+z=b-1; 得 x+y=a-b; y+z=b-1 y<=min(a-b,b-1)

枚举y,解出,x,z,然后解出 c(x+y+z,x)*C(y+z,y)*C(z,z) ,表明走x个左方向 y个下方向和z个右方向有多少种方案, 用 res加上。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
ll fact[101010],inv[101010];

const int mod=1e9+7;
const int maxn=1e5+7;

ll quickM(ll a, ll b){
    ll base = a%mod, ans = 1;
    while(b){
        if(b&1) ans = ans*base%mod;
        base = base*base%mod;
        b >>= 1; 
    }
    return ans;
}
void init(){
    fact[0] = 1;
    for(int i = 1; i <= maxn; ++i)
    fact[i] = fact[i-1]*i%mod;
    inv[maxn]=quickM(fact[maxn],mod-2);
    for(int i=maxn-1;i>=0;i--)
    {
        inv[i]=inv[i+1]*(i+1);
        inv[i]%=mod;
    }
}
ll C(int n, int m){
    return ((fact[n]*inv[m])%mod*(inv[n-m]))%mod;
}

int main()
{
    int a,b;
    init();
    while(cin>>a>>b)
    {
        long long res=0;
        int n=min(a-b,b-1);
        for(ll y=0;y<=min(a-b,b-1);y++)
        {
            ll z=b-1-y;
            ll x=a-b-y;
            res+=(C(z+y+x,x)*C(z+y,y))%mod;
            res%=mod;
        }
        printf("%lld\n",res );
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值