题解: 求从0点向m走i步那么就得返回i- m步最后原地停留了n+m-2*i步最后用排列组合就是c[n][i]*c[n-i][i-m]*A*B*C
A,B,C分别表示走了i步,i-m步,n+m-2*i步的概率C[n][i] = n!/i!/(n-i)!因为要取膜求一下逆元
最后枚举所有可能的i即可
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<cstdlib>
#include<ctime>
#include<stack>
using namespace std;
#define mes(a) memset(a,0,sizeof(a))
#define rep(i,a,b) for(i = a; i <= b; i++)
#define dec(i,a,b) for(i = b; i >= a; i--)
#define fi first
#define se second
#define ls rt<<1
#define rs rt<<1|1
#define mid (L+R)/2
#define lson ls,L,mid
#define rson rs,mid+1,R
typedef double db;
typedef long long int ll;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const int mx = 1e5+5;
const ll mod = 1e9+7;
ll A[mx];
ll B[mx];
ll modexp(ll x,ll n){
ll ans = 1;
while(n){
if(n&1) ans = ans*x%mod;
x = x*x%mod;
n /= 2;
}
return ans;
}
int main(){
A[0] = 1;
int t;
for(int i = 1; i < mx; i++)
A[i] = A[i-1]*i%mod;
B[0] = B[1] = 1;
for(int i = 1; i < mx; i++)
B[i] = modexp(A[i],mod-2);
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
m = abs(m);
if(n<m){
puts("0");
continue;
}
if(n==m){
ll ans = modexp(modexp(4,n),mod-2);
printf("%lld\n",ans);
continue;
}
ll ans = 0;
for(int i = m; 2*i <= n+m; i++){
ll sum = modexp(modexp(4,i),mod-2);
sum = sum*modexp(modexp(4,i-m),mod-2)%mod;
sum = sum*modexp(modexp(2,n-2*i+m),mod-2)%mod;
sum = sum*A[n]%mod*B[i]%mod*B[n-i]%mod;
sum = sum*A[n-i]%mod*B[i-m]%mod*B[n+m-2*i]%mod;
ans += sum;
if(ans>=mod)
ans -= mod;
}
printf("%lld\n",ans);
}
return 0;
}