思路:通过手动模拟可以发现只要终点是四个角就会满足题意的要求,所有可以暴力枚举每个起点来找出,但是复杂度不允许。。。我们从一行一列(1个小矩形)开始,向外扩展一行或一列,就会变成一个新的矩形,由于终点只能是四个角,会发现每增加一行或者一列,方案数就会是上个矩形的方案数+4.比如2行2列的方案数是8,2行3列的方案数是12,3行2列的方案数是12.
最终增加n-1行和m-1列,总共扩充n+m-2次,扩充方案数位C(n+m-2,m-1)。
所有答案为4*C(n+m-2,m-1)
需要特判一下 一行或一列的情况 方案数为2
最后用组合数打表预处理即可
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<set>
#include<bitset>
#include<map>
#include<vector>
#define int long long
#define bug cout<<"bug"<<endl;
//priority_queue <int,vector<int>,greater<int> > q;
//priority_queue <int,vector<int>,less<int> >q;
const int inf = 0x3f3f3f3f;
//const ll INF=0x7fffffffffffffff;
using namespace std;
const int mod=1e9+7;
const int N=2e6;
int fact[N];
int infact[N];
int ksm(int a,int k,int p)
{
int res=1;
while(k)
{
if(k&1)
res=res*a%p;
a=a*a%p;
k>>=1;
}
return res;
}
void init()
{
fact[0]=infact[0]=1;
for(int i=1;i<N;i++)
{
fact[i]=fact[i-1]*i%mod;
infact[i]=infact[i-1]*ksm(i,mod-2,mod)%mod;
}
}
main()
{
init();
int t;
cin>>t;
while(t--)
{
int n,m;
scanf("%lld%lld",&n,&m);
if(n==1||m==1)
{
printf("2\n");
continue;
}
printf("%lld\n",(((fact[n+m-2]*infact[n-1]%mod*infact[m-1]%mod)%mod))*4%mod);
}
}