算概率(dp,数论)

 

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

题目描述

牛牛刚刚考完了期末,尽管牛牛做答了所有 n 道题目,但他不知道有多少题是正确的。
不过,牛牛知道第 i 道题的正确率是 pi
牛牛 想知道这 n 题里恰好有 0,1,…,n 题正确的概率分别是多少,对 109+7取模。
对 109+7取模的含义是:对于一个 b≠0的不可约分数 a/b,存在 使得 b×q mod (109+7)=aq 即为 a/b 对 109+7取模的结果。

输入描述:

第一行,一个正整数 n 。
第二行,n 个整数 p1,p2,…,pn,在模 109+7意义下给出。
保证 1n2000。

输出描述:

输出一行 n+1个用空格隔开的整数表示答案(对 109+7取模)。

输入

1
500000004

输出

500000004 500000004

说明

有 1 道题,做对的概率是 1/2 ( 1/2在模 109+7意义下为 500000004 )。

 

先说一点:

mod为109+7,为质数

inv(b,mod) 表示b对mod的逆元,由费马小定理知b对mod的逆元即为bmod-2

求(a/b)%mod即为求(a*inv(b,mod))%mod,即等于该题的p。

long long fpow(long long a, long long b)
{
    if (a == 0) return 0;
    long long ans = 1;
    for (; b; b >>= 1, a = (a % mod * a% mod) % mod)
        if (b & 1) ans = (ans % mod * a % mod) % mod;
    return ans;
}
LL inv(LL a,LL mo)
{
    return fpow(a,mo-2)%mo;
} 
//求(a/b)%mod: printf("%lld\n",a*inv(b,mod)%mod);

另外注意到(a/b)%mod+(1- a/b)%mod = mod+1,由此可通过某事件概率求得其对立概率。

 

该题总体来说还是用dp来做,只不过用概率%mod(即题中p)来代替原本的概率即可。

dp[ i ][ j ] 表示前 i 道题做对 j 道的概率。

转移时考虑第 j 道题是否做对,转移方程为:dp[ i ][ j ]=dp[ i-1 ][ j ]×(1−pi)+dp[ i-1 ][ j-1 ]×pi  

时间复杂度 O(n2)

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <stack>
 9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <sstream>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const LL mod=1e9+7;
16 const int maxn=1e4+10;
17 using namespace std;
18 
19 LL P[2005];//表示第i道题做对的概率
20 LL dp[2005][2005];//dp[i][j]表示前i道题做对j道的概率
21 
22 int main()
23 {
24     #ifdef DEBUG
25     freopen("sample.txt","r",stdin);
26     #endif
27 
28     int n;
29     scanf("%d",&n);
30     for(int i=1;i<=n;i++)
31         scanf("%lld",&P[i]);
32     dp[0][0]=1;
33     for (int i = 1; i <= n; i++)
34     {
35         dp[i][0] = dp[i - 1][0] * (mod + 1 - P[i]) % mod;
36         for (int j = 1; j <= i; ++j)  //这个过程中求出来了有i题的情况下,做对0到i道题目的概率
37             dp[i][j] = (dp[i - 1][j] * (mod + 1 - P[i]) + dp[i - 1][j - 1] * P[i]) % mod;
38     }
39     for(int i=0;i<=n;i++)
40         printf(i==n?"%lld\n":"%lld ",dp[n][i]);
41 
42     return 0;
43 }

 

 

 

 

-

posted @ 2020-02-07 02:26  jiamian22  阅读(323)  评论(0编辑  收藏  举报