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
題意:
菱形的區域裏,每個位置可以從上面向左、向右或向下得到(即↙↓↘),
問從(1,1)到(a,b)共有多少種走法。
想法:
在高中學過,假設矩形的長爲len,寬度爲wid,從左上到右下(對角位置)的方法共有(len+wid)!/len!*wid!種。
記從左邊得到的爲len,從右邊得到的爲wid,從中間得到的爲c。
1.我們討論只從兩邊得到的: ans=(len+wid)!/len!*wid!;
2.一次↓ 相當於 一次↙+一次↘(就是說 對角一步走 相當於 走兩次直角邊 ):ans=(len+wid+c)!/len!*wid!*c!。所以當c++時,len-–,wid—,直到減到其中一個爲0時,結束。
因爲最後結果要取模數很大,所以要用乘法逆元,這裏選擇用線性求逆元。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int adj[5000];
const int mod=1e9+7;
typedef long long ll;
ll inv(ll b)//線性求b的逆元
{
if(b<=1)return 1;
return (mod-mod/b)*inv(mod%b)%mod;
}
int main()
{
int x,y;
ll fac[101010]={1};
ll Inv[101010]={1,1};
for(int i=1;i<100101;i++)
{
fac[i]=(fac[i-1]*i)%mod;//i的階乘
Inv[i]=inv(fac[i]);//i的階乘的逆元
}
while(~scanf("%d%d",&x,&y))
{
int right=x-y;
int left=x-1-right;
int c=0;//中路
ll ans=0;
while(right>=0&&left>=0)//所有組合方式
{
ll sum=(((fac[left+right+c]*Inv[left])%mod*Inv[right])%mod*Inv[c])%mod;
ans=(ans+sum)%mod;
left--;
right--;
c++;//一條中路相當於是一條左路加一條右路
}
printf("%lld\n",ans);
}
return 0;
}
ps:那個對角公式真的學過嗎+_+麻麻請告訴我我的高中真的存在過嗎QAQ