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;
}