两种做法:
一:枚举步数x,那么从(1,1)到(n,m)就可以看成从行1到n走了x步,从列1到m走了x步。这两个过程是独立的。所以只要将1到n走了x步的路线数乘以1到m的路线数就是(1,1)到(n,m)走x步的路线数。
问题简化为1到n走x步的路线数怎么求。
1到n路线的最小单元就是从i到i+1的路线,总共有n-1个这样的单元。
那走x步就相当于把这n-1个单元组成x个各自连续的区间段。
比如1到4,走2步,最小单元就是1-2,2-3,3-4.
那可以1-2和2-3组合,也可以2-3和3-4组合,总共两种路线。
而把这n-1个单元组成x个各自连续的区间段其实就是将n-1个相同小球放进x个不同的箱里。(隔板法,结果C(n-2,x-1))
这种方法可以向高维推广。
二:
容易发现,f(n,m)=f(n-1,2)+f(n-1,3)+……+f(n-1,m)。(n>2)
而f(2,m)=1;
进一步可以推出f(n,m)=C(n+m-4,n-2)。=。=||
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int mod=1e9+7;
int factor[200005];
LL inv(LL a,LL m) {return a==1?1:(inv(m%a,m)*(m-m/a)%m);}
int main(int argc, char const *argv[])
{
factor[0]=1;
for(int i=1;i<=200000;i++) factor[i]=(LL)factor[i-1]*(LL)i%mod;
int n,m;
while(scanf("%d%d",&n,&m)==2){
int ans=(LL)factor[n+m-4]*inv(factor[n-2],mod)%mod*inv(factor[m-2],mod)%mod;
printf("%d\n",ans );
}
return 0;
}