久未动笔,有些生疏。
题意:柯南在零秒时,从零点开始出发,每一秒向左向右走的概率各为0.5,求m秒后在n处的概率p/q。输出
z∗q≡pmod1e9+7
z
∗
q
≡
p
m
o
d
1
e
9
+
7
分析:这道题2017秦皇岛CCPC最后一题(如果没记错的话)出现过类似的,不过当时是二位空间求概率。2018年的川大校赛也出现过然而那个出成了水题……
通过简单分析我们可以得知以下规律:

即分子遵循杨辉三角定律,分母为2^m。
然后就是找n与第m行第几个数有关的规律了,这里借鉴了一位大佬的思路,大概也就是我面对这种题目欠缺的地方。https://blog.youkuaiyun.com/sdau20163942/article/details/80302729
说起来这还是第一次认真的解决掉杨辉三角相关……
如果n<=m,此时能够到达n,假设n在左边,假设往左走了l步,往右走了r步,有公式 ①.l+r=m;②l-r=n;可得l=(m+n)/2
然后结合Lucas定理,得出结果。
AC代码:
#include<bits/stdc++.h>
#define LL long long
#define maxn 2e5+7
using namespace std;
const long long mod = 1000000000+7;
LL b[200000+7],inv[200000+7];
LL powmod(LL n,LL k,LL mo){
LL res=1;
n%=mo;
while(k>0){
if(k&1) res=res*n%mo;
n=n*n%mo;
k>>=1;
}
return res;
}
void ini(){
b[0]=inv[0]=1;
for(int i=1;i<=maxn;i++){
b[i]=(b[i-1]*i)%mod;
inv[i]=powmod(b[i],mod-2,mod);
}
}
LL C(LL n,LL m){
if(n<m) return 0;
return b[n]*inv[m]%mod*inv[n-m]%mod;
}
LL Lucas(LL n,LL m){
if(m==0) return 1;
return C(n%mod,m%mod)*Lucas(n/mod,m/mod)%mod;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
int T;
cin>>T;
ini();
while(T--){
LL n,m;
cin>>n>>m;
n=abs(n);
LL ans;
if(n==0 && m==0){
cout<<1<<endl;
continue;
}
if(n>m || (m-n)&1){
cout<<0<<endl;
continue;
}
LL q=powmod(2,m,mod);
LL p=Lucas(m,m-(m+n)/2);
ans=p*powmod(q,mod-2,mod)%mod;
cout<<ans<<endl;;
}
return 0;
}
总结:意外地发现了Gloria小盆友的Lucas大数模板有问题。。。所以代码和大佬的很像= =
Lucas:解决组合数,杨辉三角的好盆友~