开学考试题4:book 书(概率期望dp)

题目:

                  书

Hazel有n本书,编号1为n到 ,叠成一堆。当她每次抽出一本书的时候,上方的书会因重力而下落,这本被取出的书则会被放置在书堆顶。

每次有pi的概率抽取编号为i的书。她每次抽书所消耗的体力与这本书在这堆中是第几本成正比。具体地,抽取堆顶的书所耗费体力值为1 ,抽取第二本耗费体力值为2 ,以此类推。

现在 想知道,在很久很久以后(可以认为几乎是无穷的),她每次抽书所耗费的体力的期望值是多少。

最终的答案显然可以表示成a/b的形式,请输出a*(b^-1)模1e9+7的值。

【输入格式】

第一行一个整数n

接下来n行,每行两个整数ai,bi,代表抽取第i本书的概率是ai/bi

保证所有书的概率和等于1

分析:

通过抽书而改变的排列顺序,一共有n!种,当抽书的次数无限多时,每一种排列方式的概率相同。

枚举排列方式来统计答案,复杂度很高,所以考虑每一本书对答案的贡献。

ans=抽到这本书的概率 * 这本书的期望体力消耗。

这本书的期望体力消耗=其他书放在它上面使它产生多1 的体力

即 ∑ j:(1~n 且 j!=i)p [ j ] / ( p[ i ]+p[ j ])。(抽到这两本书的概率*先抽 j 的概率)//

当然,即使没有书放在它上面,也要产生1的体力,所以要+1。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 1005
#define ri register int
const ll mod=1e9+7;
ll a[N],b[N],p[N];
ll quick_pow(ll a,ll k)
{
    ll ans=1;
    while(k){ if(k&1) ans=ans*a%mod; a=a*a%mod; k>>=1; }
    return ans;
}
int main()
{
    freopen("book.in","r",stdin);
    freopen("book.out","w",stdout);
    int n;
    scanf("%d",&n);
    for(ri i=1;i<=n;++i) scanf("%lld%lld",&a[i],&b[i]),p[i]=a[i]*quick_pow(b[i],mod-2) %mod;
    ll ans=0;
    for(ri i=1;i<=n;++i){
        ll tmp=0;
        for(ri j=1;j<=n;++j)
        if(i!=j) tmp=( tmp+ p[j]*quick_pow(p[i]+p[j],mod-2) %mod ) %mod;
        ans=( ans+p[i]*(tmp+1)%mod )%mod;
    }
    printf("%lld
",ans);
}
/*
2
227494 333333
105839 333333

10
159073 999999
1493 142857
3422 333333
4945 37037
2227 111111
196276 999999
190882 999999
142721 999999
34858 999999
101914 999999
*/
View Code
原文地址:https://www.cnblogs.com/mowanying/p/11529066.html