exawizards2019e

我甚至不知道这是什么比赛qaq

题目大意

有 $b$ 和 $w$ 两个数,每一次选择其中一个数减 1,直到两个数都变成 0。选择的规则如下:

如果两个数都大于 0,则等概率选择一个;

否则选择比 0 大的数。

求每一时刻取 1 的概率,对 $1e9+7$ 取模。

solution

考虑将每一时刻时的状态分成 3 种:$b$ 和 $w$ 都有剩余,只剩下 $b$,只剩下 $w$。

第一种情况只需要将概率乘上 2 的逆元即可,但是概率比较难求。我们先放一边。

第二种和第三种求概率的本质是相同的,只不过答案只需加上第二种。

考虑第二种和第三种概率的求法。以第二种为例,发现取完的时刻为 $t$ 时的概率为 $\large f_i=\binom{t-1}{b-1}\times 2^t$,时刻为 $t$ 时取完的总概率即为 $\sum_{i=1}^{t}f_i$,递推即可。

显然求出后面两种概率的之后可以反推出第一种的概率。

时间复杂度 $O(b+w)$。

code

#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL n,i,j,k,m;
LL val[200005];
LL pow2[200005];
LL p1[200005],p2[200005];
const LL mod=1000000007;
void exgcd(LL a,LL b,LL &x,LL &y,LL &val){
    if(b==0){
        val=a;
        x=1;
        y=0;
    }
    else{
        exgcd(b,a%b,y,x,val);
        y-=x*(a/b);
    }
}
LL inv(LL x){
    LL tmp1=0,tmp2=0,tmp3=0;
    exgcd(x,mod,tmp1,tmp2,tmp3);
    return (tmp1%mod+mod)%mod;
}
LL C(LL x,LL y){
    return val[x]*inv(val[y])%mod*inv(val[x-y])%mod;
}
int main() {
    val[0]=1;
    pow2[0]=1;
    for(i=1;i<=200000;i++){
        val[i]=val[i-1]*i;
        pow2[i]=pow2[i-1]<<1ll;
        val[i]%=mod;
        pow2[i]%=mod;
    }
    scanf("%lld%lld",&n,&m);
    p1[m]=inv(pow2[m]);
    for(i=m+1;i<n+m;i++){
        p1[i]=p1[i-1]+C(i-1,m-1)*inv(pow2[i])%mod;
        p1[i]%=mod;
    }
    p2[n]=inv(pow2[n]);
    for(i=n+1;i<n+m;i++){
        p2[i]=p2[i-1]+C(i-1,n-1)*inv(pow2[i])%mod;
        p2[i]%=mod;
    }
    for(i=0;i<n+m;i++){
        LL p=1,ans=0;
        if(i>=m){
            p-=p1[i];
            p=(p%mod+mod)%mod;
            ans+=p1[i];
        }
        if(i>=n){
            p-=p2[i];
            p=(p%mod+mod)%mod;
        }
        ans+=p*inv(2);
        printf("%lld\n",ans%mod);
    }
    return 0;
}
posted @ 2023-10-08 13:38  monster_hunterqwq  阅读(9)  评论(0编辑  收藏  举报  来源