牛客练习赛46-华华跟奕奕玩游戏(期望+逆元)

链接:https://ac.nowcoder.com/acm/contest/894/C
来源:牛客网

题目描述

有一个箱子,开始时有n个黑球,m个蓝球。每一轮游戏规则如下:
第一步:奕奕有p的概率往箱子里添加一个黑球,有(1-p)的概率往箱子里添加一个蓝球。
第二步:华华随机从箱子里取出一个球。
华华喜欢黑球,他想知道k轮游戏之后箱子里黑球个数的期望。

输入描述:

输入五个整数n,m,k,a,b。
1<=n,m<=1e6,1<=k<=1e9
其中p=abab,且a<=b,0<=a<1e9+7,0<b<1e9+7

输出描述:

输出一个数表示k轮游戏后箱子里黑球个数的期望。
输出一个整数,为答案对1e9+7取模的结果。即设答案化为最简分式后的形式为abab,其中a和b互质。输出整数 x 使得bx≡a(mod 1e9+7)且0≤x<1e9+7。可以证明这样的整数x是唯一的。

示例1

输入

2 2 1 1 2

输出

2

示例2

输入

2 2 2 3 10

输出

184000003

题意:如上

思路:求期望题目,一遍是逆推,但是这个好像推不出?看了题解后,我推出来的式子和题解一样,但是过程貌似有点出入,后面再研究研究了。我的思路是,对于第i天的黑球期望 dp[i] = dp[i-1] + p*1 - (dp[i-1] + p*1)(m+n+1),直观上理解,第i天黑球期望等于前一天的期望数加上第一步取得黑球的期望 p*1 ,再减去第二步取出黑球的期望,注意到无论哪一轮,第二步的时候总球数一定是n+m+1,则随机取到黑球期望为 (dp[i-1] + p*1)/(n+m+1)*1。就可以推到dp[i]了。化简后可以用矩阵快速幂算,进一步化简后只需算一个等比数列,用快速幂推就可以了。

题解思路:

注意:本题学的东西还是挺多的,主要是逆元和模方面的细节,以前虽然知道但是没有做过,感觉还是不一样。含模运算过程如果有减法一定要(a-b)%mod = ((a%mod-b%mod)+mod)%mod,不然会出错。

#include<bits/stdc++.h>
#include<iostream>
#include<queue>
#include<cstring>
#include<math.h>
#include<algorithm>
#include<cstdio>
#include<map>
#include<stack>
#include<vector>
#define rep(i,e) for(int i=0;i<(e);++i)
#define rep1(i,e) for(int i=1;i<=(e);++i)
#define repx(i,x,e) for(int i=(x);i<=(e);++i)
#define pii pair<int,int>
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
typedef long long ll;
using namespace std;

#ifdef LOCAL
template<typename T>
void dbg(T t){
    cout<<t<<" "<<endl;
}
template<typename T, typename... Args>
void dbg(T t, Args... args){
    cout<<t<<" ";dbg(args...);
}


#else
#define dbg(...)
#endif // local
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const int mod = 1e9+7;
const int N = 1e4+10;
typedef long long ll;
#define K 137
const int maxn = 1e3+10;
const int maxm =4e5+10;

ll qpow(ll x,ll n){
    ll res = 1;
    while(n){
        if(n % 2 == 1)
            res = res*x%mod;
        x  = x*x%mod;
        n /= 2;
    }
    return res;
}

void work(){
    ll n,m,k,a,b;
    cin>>n>>m>>k>>a>>b;
    ll p = a*qpow(b,mod-2)%mod;
    ll s = (n+m)%mod*qpow(n+m+1,mod-2)%mod;
    ll cc = n*qpow(s,k)%mod;
    ll aa = p*(((s-qpow(s,k+1)%mod)+mod)%mod)%mod*qpow(((1-s)+mod)%mod,mod-2)%mod;//**注意
    cout<<(cc+aa)%mod<<endl;

}


int main()
{
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif // LOCAL
    IOS;
    work();
    return 0;
}
题解参考代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod=1e9+7;
ll pow1(ll a,ll b)
{
    ll r=1;
    while(b)
    {
        if(b&1)
            r=r*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return r;
}
int main()
{
    int n,m,k,a,b;
    scanf("%d%d%d%d%d",&n,&m,&k,&a,&b);
    ll p=1LL*a*pow1(b,mod-2)%mod;
    ll s=1LL*(n+m)*pow1(n+m+1,mod-2)%mod;
    ll ans=1LL*n*pow1(s,k)%mod+p*(s-pow1(s,k+1))%mod*pow1(1-s,mod-2)%mod;
    ans=ans%mod+mod;   //********注意
    printf("%lld\n",ans%mod);
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值