先把题面贴一下吧:
首先感谢青科大授权 SDUT-OJ 挂题~~~
省赛重现链接:2017 “浪潮杯”山东省第八届ACM大学生程序设计竞赛 重现
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.
Example Input
1 1 3 2 100000 100000
Example Output
1 3 1
Hint
Author
题目大意:
给出一个蜂窝状图,从(1,1)开始,每次可以移动一步,有左下、右下、下三个方向,给出指定坐标,问一共有多少种走法,答案对1e9+7取模。
回来后我在上课的时候推了一下就推出来了,确实和C题非常像,甚至只需要改改主逻辑就可以。。。
上解题思路:
1,最大步数,为x-1,即为全部左走或者右走的步数;
2,距离(1,1)的横向偏移量,为(x+1-2*y)(设左偏为正)。
利用这两个数据,即可推算出结果:
首先考虑全部左走或右走,即最大步数的情况,设左走为a,右走为b,下走为c,可得a+b=x-1,a-b=x+1-2*y,c=0,解出a和b,这部分的答案即为A(a+b+c,a+b+c)/(A(a,a)*A(b,b)*A(c,c));
然后考虑每一步下走相当于一次左走加一次右走,则每次a--,b--,c++,直到a,b其中一个或者全部为0,对于每次操作,可得结果也为A(a+b+c,a+b+c)/(A(a,a)*A(b,b)*A(c,c)),
累加结果即可,取模问题也是用乘上乘法逆元再取模的方法解决。。不会乘法逆元的可以先去学习一下。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL i,x,y,a,b,c,ans,p[112345],mod=1e9+7,n[112345];
LL exgcd(LL a,LL b,LL &x,LL &y){
if(!b){
x=1,y=0;
return a;
}
LL r=exgcd(b,a%b,x,y),temp=x;
x=y,y=temp-a/b*y;
return r;
}
LL cal(LL a,LL m){
LL ans,x,y,gcd=exgcd(a,m,x,y);
if(1%gcd)
return -1;
x*=1/gcd,m=abs(m),ans=x%m;
if(ans<=0)
ans+=m;
return ans;
}
int main(){
p[0]=1,n[0]=cal(p[0],mod);
for(i=1;i<112345;i++)
p[i]=(p[i-1]*i)%mod,n[i]=cal(p[i],mod);
while(~scanf("%lld %lld",&x,&y)){
ans=c=0,a=x-y,b=x-a-1;
while(~a&&~b)
ans=(ans+p[a+b+c]*n[a]%mod*n[b]%mod*n[c]%mod)%mod,a--,b--,c++;
printf("%lld\n",ans);
}
return 0;
}