题意:
给定n,m,n代表小A能走的步数m代表最后要到达的位置。
每次走有三种选择1/4向左1/4向右1/2待在原地,问最后n步到达
m位置的概率%Mod(1e9+7)
分析:
经过分析我们可以讲答案分解
res += C(n,i)*C(n-i,i-m)*p[x];
x代表到达当前状态的概率;
C(n,i)//从n步当中抽取i步是1
C(n-i,i-m)//从剩下的n-i步中抽取i-m步是-1
剩下的全部都是0
这里我用的是费马小定理。与处理出阶乘和阶乘的逆元。
for(i=1,fat[0]=finv[0]=1;i<N;i++){
fat[i]=fat[i-1]*i%Mod;
finv[i]=finv[i-1]*inv(i)%Mod;
}
再与预处理出p
for(i=2,p[1]=inv(2),p[0]=1;i<3*N;i++){
p[i]=p[i-1]*p[1]%Mod;
}
完事。。:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 100005
#define LL long long
#define Mod 1000000007
LL fat[N],finv[N],p[3*N],i,j,n,m;
LL quick(LL x,LL n){
LL res=1;
while(n){
if(n%2)res=res*x%Mod;
x=x*x%Mod;
n/=2;
}
return res;
}
LL inv(LL x){
return quick(x,Mod-2);
}
void init(){
for(i=1,fat[0]=finv[0]=1;i<N;i++){
fat[i]=fat[i-1]*i%Mod;
finv[i]=finv[i-1]*inv(i)%Mod;
}
p[0]=1;
for(i=2,p[1]=inv(2);i<3*N;i++){
p[i]=p[i-1]*p[1]%Mod;
}
return;
}
LL C(LL n,LL m){
if(m<0||m>n)return 0;
return fat[n]*finv[m]%Mod*finv[n-m]%Mod;
}
int main(){
init();
int T;
scanf("%d",&T);
while(T--){
scanf("%lld %lld",&n,&m);
LL res=0;
for(i=0;i<=n;i++){
LL x = i - m,y=(n-i-x);
if(x<0||x>n||y<0||y>n)continue;
res =(res+C(n,i)*C(n-i,x)%Mod*p[(i+x)*2+y])%Mod;
}
printf("%lld\n",res);
}
}