HEX (combinatorial mathematics + inverse element + thinking)

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

Hint

Source

"Inspur Cup" Shandong Province 8th ACM College Student Programming Competition (Thanks to Qingdao University of Science and Technology)

The meaning of the question: Find the total number of options from (1,1) to (a,b)

Idea: From the current grid, you can move to the bottom left, bottom right, and directly below, then

   (1,1)+x*(1,0)+y*(2,1)+z*(1,1)=(a,b)

所以:x+y=a-b, y+z = b-1;    0<=y<=min(b-1,a-b)

For each y, the number of solutions ans=C(x+y+z,x)*C(y+z,x);

Since the number of combinations is relatively large, the inverse element idea is used to deal with it.

Code:

#include<cstdio>
#include<cstring>
#include<string>
#define mod 1000000007
using namespace std;
typedef long long LL;
const int N = 100000;
LL fact[N+5],inv[N+5];
LL q_pow(LL x,LL y){
	LL ans=1;
	while(y){
		if(y&1) ans=ans*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return ans;
}
void init(){
	fact[0]=1;
	for(int i=1;i<=N;i++)
	   fact[i]=fact[i-1]*i%mod;
	inv[N]=q_pow(fact[N],mod-2);
	for(int i=N-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(){
	init();
	int a,b;
	while(scanf("%d%d",&a,&b)!=EOF){
		LL ans=0;
		int n=min(a-b,b-1);
		for(int y=0;y<=n;y++){
			int z=b-1-y;
			int x=a-b-y;
			ans+=(C(x+y+z,x)*C(z+y,y))%mod;
			ans% = mod;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325900113&siteId=291194637