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

Hint

Source

“浪潮杯”山东省第八届ACM大学生程序设计竞赛(感谢青岛科技大学)

题意:求从(1,1)走到(a,b)一共有多少种方案数

思路:从当前一格可以向左下,右下,正下方移动,则

   (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)

对于每个y时,方案数ans=C(x+y+z,x)*C(y+z,x);

由于组合数比较大,用逆元思想来处理

代码:

#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;
}

猜你喜欢

转载自blog.csdn.net/islittlehappy/article/details/80182671
今日推荐