2020牛客寒假算法基础集训营2 C 算概率
题目描述
牛牛刚刚考完了期末,尽管牛牛作答了所有的道题,但他也不知道有多少道题是正确的。
不过,牛牛知道第道题目的正确率是
牛牛想知道这道题里,恰好做对0,1,2···n道题目的概率分别是多少,对
取模
对取模的含义是:对于一个
的不可约分分数
,存在
使得
,
即为
对
取模的结果
思路
首先可以看出这是一个概率题目,对于恰好个对,就是每一个都错的概率相乘,对于恰好
个对,就是任选
个对的概率,乘以其余不对概率,最后求和。
思路没问题,但是如果想通过这样的方式AC,是不可能的,时间复杂度太大了。
可以往概率dp上面考虑,令的含义是,前
个题目对了
的概率,可以通过dp的手段,一步一步探索道
,
就是一共
个题目恰好对了
个的概率,然后依次输出。
第一次接触概率dp,比赛的时候很懵
转移方程很简单,首先考虑 的来源,显然前
个对
个的概率可以有前面的
个对
个,然后当前这个错误,可以这么推到出来(前提是
),还可以是,前
个对了
的概率,乘以当前这个题目对了概率,依次递推即可,初始状态就是
第一个错误的概率,
第一个正确的概率。题目中说的取模
的意义可以不考虑,直接把给出的数字当作正确的概率,错误的概率是
正确的概率,计算过程中对
取模就可以了
code
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof a)
const int N = 2010;
const int mod = 1e9 + 7;
typedef long long ll;
ll f[N][N];
int n;
ll a[N];
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)scanf("%lld", a + i);
mem(f, 0);
f[1][1] = a[1];
f[1][0] = mod + 1 - a[1];
for (int i = 2; i <= n; i++){
f[i][0] = f[i - 1][0] * (mod + 1 - a[i]) % mod;
for (int j = 1; j <= i; j++){
f[i][j] = f[i - 1][j] * (mod + 1 - a[i]) % mod + f[i - 1][j - 1] * (a[i]) % mod;
f[i][j] %= mod;
}
}
for (int i = 0; i <= n; i++){
printf("%lld ", f[n][i]);
}
return 0;
}
本文来自博客园,作者:correct,转载请注明原文链接:https://www.cnblogs.com/correct/p/12861962.html

浙公网安备 33010602011771号