牛客练习赛46----C-华华跟奕奕玩游戏

首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/894/C
来源:牛客网
涉及:逆元,递推式


题目如下:
牛客练习赛46----C-华华跟奕奕玩游戏
牛客练习赛46----C-华华跟奕奕玩游戏
关于这个题首先要抓住一个重点,就是每一轮过后,期望就会发现变化,即:

相邻两轮游戏后的期望值是有一个递推关系的

假设第kk轮后黑球数量的期望是a[k]

只要先找到a[k]与a[k+1]的关系,然后通过递推关系找到a[k]的通项公式,并把a[k]的通项公式表示为分数的形式,然后利用分数取模找逆元,就可以得到答案。


首先找递推公式:

由于每一轮游戏都会放入一个球,并拿走一个球,所以盒子中球的数量肯定是不变的

由于第k轮后盒子里还剩a[k]个球,那么第k+1轮后,盒子里的黑球数量只有三种可能:
  1.多放了一个黑球,即有a[k]+1个球;
  2.仍然是a[k]个球;
  3.拿走了一个黑球,即有a[k]-1个球;

在来考虑每一种情况的概率:
1.多放了一个黑球,即有a[k]+1个黑球
 则第k+1轮放了一个黑球(注意此时盒子里应该有n+m+1个球,有a[k]+1个黑球),拿了一个蓝球
 
放黑球的概率是p,拿蓝球的概率是n+m+1a[k]1n+m+1\frac{n+m+1-a[k]-1}{n+m+1},则此情况的概率:
p(n+m+1a[k]1)n+m+1\frac{p*(n+m+1-a[k]-1)}{n+m+1}
 
2.拿走了一个黑球,即有a[k]-1个黑球
 则第k+1轮放了一个蓝球(注意此时盒子里应该有n+m+1个球,有a[k]个黑球),拿了一个黑球

放蓝球的概率是(1-p),拿黑球的概率是a[k]n+m+1\frac{a[k]}{n+m+1},则此情况的概率:
(1p)a[k]n+m+1\frac{(1-p)*a[k]}{n+m+1}
 
3.仍然是a[k]个球(此情况有两种可能)
 当第k+1轮放了一个蓝球(注意此时盒子里应该有n+m+1个球,有a[k]个黑球),则拿了一个蓝球
 
放蓝球的概率是(1-p),拿蓝球的概率是n+m+1a[k]n+m+1\frac{n+m+1-a[k]}{n+m+1}
 
 当第k+1轮放了一个黑球(注意此时盒子里应该有n+m+1个球,有a[k]+1个黑球),则拿了一个黑球
 
放黑球的概率是p,拿黑球的概率是a[k]+1n+m+1\frac{a[k]+1}{n+m+1}

则此情况概率为:
(1p)(n+m+1a[k])n+m+1+p(a[k]+1)n+m+1\frac{(1-p)*(n+m+1-a[k])}{n+m+1}+\frac{p*(a[k]+1)}{n+m+1}

情况 k+1轮后黑球个数 此情况概率
多放了一个黑球 a[k]+1 p(n+m+1a[k]1)n+m+1\frac{p*(n+m+1-a[k]-1)}{n+m+1}
拿走了一个黑球 a[k]-1 (1p)a[k]n+m+1\frac{(1-p)*a[k]}{n+m+1}
仍然是a[k]个球 a[k] (1p)(n+m+1a[k])n+m+1+p(a[k]+1)n+m+1\frac{(1-p)*(n+m+1-a[k])}{n+m+1}+\frac{p*(a[k]+1)}{n+m+1}

如上表所示,a[k+1]期望为:
[a[k]+1n+m+1a[k]+n+m+1a[k]1n+m+1(a[k]+1)]p[\frac{a[k]+1}{n+m+1}a[k]+\frac{n+m+1-a[k]-1}{n+m+1}(a[k]+1)]p
+[n+m+1a[k]n+m+1a[k]+a[k]n+m+1(a[k]1)](1p)+[\frac{n+m+1-a[k]}{n+m+1}a[k]+\frac{a[k]}{n+m+1}(a[k]-1)](1-p)
经化简可得:
a[k+1]=(a[k]+p)n+mn+m+1a[k+1]=(a[k]+p)\frac{n+m}{n+m+1}


再找通项公式:

为了方便计算,我们设尝数q=n+mn+m+1\frac{n+m}{n+m+1}

即:
a[k+1]=q(a[k]+p)=qa[k]+qpa[k+1]=q(a[k]+p)=q*a[k]+qp

为了得到通项公式,再设常数x,使得
a[k+1]+x=q(a[k]+x)=qa[k]+qxa[k+1]+x=q(a[k]+x)=q*a[k]+qx

则qx-x=qp,解得
x=qpq1x=\frac{qp}{q-1}

又因为a[0]=n,可以得到:

a[k]+qpq1a[k]+\frac{qp}{q-1}是以(n+qpq1)(n+\frac{qp}{q-1})为首项,q为公比的等比数列


a[k]+qpq1=(n+qpq1)qk (k0)a[k]+\frac{qp}{q-1}=(n+\frac{qp}{q-1})*q^{k} (k\ge0)

a[k]=(n+qpq1)qkqpq1 (k0)a[k]=(n+\frac{qp}{q-1})*q^{k}-\frac{qp}{q-1} (k\ge0)
最后,把p=ab,q=n+mn+m+1p=\frac{a}{b},q=\frac{n+m}{n+m+1}代入,得到
a[k]=[nab(n+m)](n+m)k(n+m+1)k+ab(n+m)a[k]=[n-\frac{a}{b}(n+m)]\frac{(n+m)^{k}}{(n+m+1)^{k}}+\frac{a}{b}(n+m)
分数统一化,得到
a[k]=(bnanam)(n+m)k+a(n+m)(n+m+1)kb(n+m+1)k  (k0)a[k]=\frac{(bn-an-am)(n+m)^{k}+a(n+m)(n+m+1)^{k}}{b(n+m+1)^{k}}  (k\ge0)


分数取模,找逆元:

最后期望
分子fa
fa=(bnanam)(n+m)k+a(n+m)(n+m+1)kfa=(bn-an-am)(n+m)^{k}+a(n+m)(n+m+1)^{k}
分母fb
fb=b(n+m+1)kfb=b(n+m+1)^{k}
我们只考虑余数,所以还需讲fa与fb对mod取余

ll pa=qPow_function(n+m+1,k,mod);
ll pb=qPow_function(n+m,k,mod);
ll fa=((b*n%mod-a*n%mod-a*m%mod)*pb%mod+((a*(n+m)%mod)%mod*pa)%mod)%mod;//多用取余,不然很可能就爆
ll fb=b*pa%mod;

分数取模(abMODp\frac{a}{b}MOD p),由于mod=1e9+7是一个质数,可以使用费马小定理求解

abMODp=(ac)MODp\frac{a}{b}MOD p=(a*c)MODp
(其中c是b MOD mod的逆元,mod是质数,因此c=bp-2%p)

ll ni=qPow_function(fb,mod-2,mod);//ni是逆元
return !(cout<<(fa*ni%mod+mod)%mod);//注意fa可能是负数,所以要再加mod并模上mod

举例子:
过程只有套fa和fb以及求逆元公式,过于简单,不用举例子,注意要用快速幂(n+m)k(n+m)^{k}(n+m+1)k(n+m+1)^{k}


代码如下:

#include <iostream>
#define mod (ll)1000000007
using namespace std;
typedef long long ll;
ll n,m,k,a,b;
long long qPow_function(long long _x,long long _divisor,long long _mod){//快速幂
    long long sum=1;
    while(_divisor){
        if(_divisor&1)    sum=sum*_x%_mod;
        _divisor=_divisor>>1;
        _x=_x*_x%_mod;
    }
    return sum;
}
int main(){
	cin>>n>>m>>k>>a>>b;
	ll pa=qPow_function(n+m+1,k,mod);//pa是(n+m+1)的k次方
	ll pb=qPow_function(n+m,k,mod);//pb是(n+m)的k次方
	ll fa=((b*n%mod-a*n%mod-a*m%mod)*pb%mod+((a*(n+m)%mod)%mod*pa)%mod)%mod;//套fa公式得分子
	ll fb=b*pa%mod;//套公式
	ll ni=qPow_function(fb,mod-2,mod);//求fb模mod的逆元
	return !(cout<<(fa*ni%mod+mod)%mod);
}