gym101778A(Lucas定理)

本文介绍了一种基于杨辉三角和Lucas定理的概率计算问题,柯南在一维空间中随机行走,求特定时间和位置的概率。文章给出了详细的解题思路和AC代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

久未动笔,有些生疏。
题意:柯南在零秒时,从零点开始出发,每一秒向左向右走的概率各为0.5,求m秒后在n处的概率p/q。输出

zqpmod1e9+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:解决组合数,杨辉三角的好盆友~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值