牛客等级之题N1(8.3) (数论递推通项公式)
链接:https://ac.nowcoder.com/acm/contest/6766/A
题目描述
有一个箱子,开始时有n个黑球,m个蓝球。每一轮游戏规则如下:
第一步:奕奕有p的概率往箱子里添加一个黑球,有(1-p)的概率往箱子里添加一个蓝球。
第二步:华华随机从箱子里取出一个球。
华华喜欢黑球,他想知道k轮游戏之后箱子里黑球个数的期望。
第一步:奕奕有p的概率往箱子里添加一个黑球,有(1-p)的概率往箱子里添加一个蓝球。
第二步:华华随机从箱子里取出一个球。
华华喜欢黑球,他想知道k轮游戏之后箱子里黑球个数的期望。
输入描述:
输入五个整数n,m,k,a,b。
1<=n,m<=1e6,1<=k<=1e9
其中p=ab\frac{a}{b}ba,且a<=b,0<=a<1e9+7,0<b<1e9+7
输出描述:
输出一个数表示k轮游戏后箱子里黑球个数的期望。
输出一个整数,为答案对1e9+7取模的结果。即设答案化为最简分式后的形式为ab\frac{a}{b}ba,其中a和b互质。输出整数 x 使得bx≡a(mod 1e9+7)且0≤x<1e9+7。可以证明这样的整数x是唯一的。
示例
输入
2 2 1 1 2
输出
2
输入
2 2 2 3 10
输出
184000003
题解:
关于这个题首先要抓住一个重点,就是每一轮过后,期望就会发现变化,即:
相邻两轮游戏后的期望值是有一个递推关系的
假设第k轮后黑球数量的期望是a[k]
只要先找到a[k]与a[k+1]的关系,然后通过递推关系找到a[k]的通项公式,并把a[k]的通项公式表示为分数的形式,然后利用分数取模找逆元,就可以得到答案。
参考链接:https://blog.csdn.net/weixin_43702895/article/details/90343536#commentBox
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <bits/stdc++.h> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn=5e5+7; const ll mod =1e9+7; ll mul(ll a, ll b){//防止溢出 ll ans = 0; while (b){ if(b & 1){ ans = (ans+a)%mod; } a = (a+a)%mod; b = b>>1; } return ans; } ll quickpow(ll a, ll b){ ll ans = 1, base = a%mod; while (b){ if(b & 1){ ans = mul(ans, base)%mod; } base = mul(base, base)%mod; b = b>>1; } return ans; } int main(){ ll n,m,k,a,b; scanf("%lld%lld%lld%lld%lld",&n,&m,&k,&a,&b); //cout<<n<<" "<<m<<" "<<k<<" "<<a<<" "<<b<<endl; ll pa=quickpow(n+m+1,k); ll pb=quickpow(n+m,k); 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; ll inv=quickpow(fb,mod-2); printf("%lld\n",(fa*inv%mod+mod)%mod); return 0; }