牛客练习赛46----C-华华跟奕奕玩游戏
首先发出题目链接:
链接:https://ac.nowcoder.com/acm/contest/894/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,拿蓝球的概率是,则此情况的概率:
2.拿走了一个黑球,即有a[k]-1个黑球
则第k+1轮放了一个蓝球(注意此时盒子里应该有n+m+1个球,有a[k]个黑球),拿了一个黑球
放蓝球的概率是(1-p),拿黑球的概率是,则此情况的概率:
3.仍然是a[k]个球(此情况有两种可能)
当第k+1轮放了一个蓝球(注意此时盒子里应该有n+m+1个球,有a[k]个黑球),则拿了一个蓝球
放蓝球的概率是(1-p),拿蓝球的概率是;
当第k+1轮放了一个黑球(注意此时盒子里应该有n+m+1个球,有a[k]+1个黑球),则拿了一个黑球
放黑球的概率是p,拿黑球的概率是
则此情况概率为:
情况 | k+1轮后黑球个数 | 此情况概率 |
---|---|---|
多放了一个黑球 | a[k]+1 | |
拿走了一个黑球 | a[k]-1 | |
仍然是a[k]个球 | a[k] |
如上表所示,a[k+1]期望为:
经化简可得:
再找通项公式:
为了方便计算,我们设尝数q=
即:
为了得到通项公式,再设常数x,使得
则qx-x=qp,解得
又因为a[0]=n,可以得到:
是以为首项,q为公比的等比数列
则
即
最后,把代入,得到
分数统一化,得到
分数取模,找逆元:
最后期望
分子fa
分母fb
我们只考虑余数,所以还需讲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;
分数取模(),由于mod=1e9+7是一个质数,可以使用费马小定理求解
(其中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以及求逆元公式,过于简单,不用举例子,注意要用快速幂求和
代码如下:
#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);
}