有一个无限大的矩形,初始时你在左上角(即第一行第一列),每次你都可以选择一个右下方格子,并瞬移过去(如从下图中的红色格子能直接瞬移到蓝色格子),求到第n行第m列的格子有几种方案,答案对1000000007取模。
Input
多组测试数据。
两个整数n,m(2≤n,m≤100000)
Output
一个整数表示答案
Sample Input
4 5
Sample Output
10
Source
2016"百度之星" - 初赛(Astar Round2B)
Recommend
wange2014 | We have carefully selected several similar problems for you: 6396 6395 6394 6393 6392
首先我们分析一下这个题其实就是我们要从(1, 1)点走到(n, m)点,而且只能走右下方,那么我们就相当于从(n+m-4)个格子里选n-2(或者是m-2)个格子,因为我们得去掉n-1行和m-1列(这个不能选),然后再去掉第一行和第一列,所以就是
C(m+n−4,n+2)=(n+m−4)!(n−2)!∗(m−2)!
卢卡斯定理对大数取模
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const ll p=1e9+7;
ll multi(ll a,ll b,ll m)
{
ll ans=0;
a%=m;
while(b)
{
if(b&1)
{
ans=(ans+a)%m;
b--;
}
b>>=1;
a=(a+a)%m;
}
return ans;
}
ll quick_mod(ll a,ll b,ll m)
{
ll ans=1;
a%=m;
while(b)
{
if(b&1)
{
ans=multi(ans,a,m);
b--;
}
b>>=1;
a=multi(a,a,m);
}
return ans;
}
ll getc(ll n,ll m)
{
if(n<m)
return 0;
if(m>n-m);
m=n-m;
ll s1=1,s2=1;
for(ll i=0;i<m;i++)
{
s1=s1*(n-i)%p;
s2=s2*(i+1)%p;
}
return s1*quick_mod(s2,p-2,p);
}
ll lucas(ll n,ll m)
{
if(m==0)
return 1;
return getc(n%p,m%p)*lucas(n/p,m/p)%p;
}
int main()
{
ll n, m;
while(~scanf("%lld%lld",&n,&m))
{
printf("%lld\n",lucas(n+m-4,n-2));
}
return 0;
}