<题目链接>
题目描述
小a有$n$个烟花,每个烟花代表着互不相同的颜色,对于第$i$个烟花,它有$p_i$的概率点燃,现在小a要去点燃它们,他想知道产生颜色的期望个数 及 产生恰好产生$k$种颜色的概率。
对于$100%$的数据$(n leq 10^5 ,k leq 2 imes 10^2)$输出均保留4位小数,若你的答案误差与std不超过$10^{-4}$即为正确
解题分析:
本题是比较经典的dp,$dp[i][j]$表示前i件物品中产生j件物品的概率,不难想到,状态转移方程为:$dp[i][j] = dp[i-1][j]*(1-p[i])+dp[i-1][j-1]*p[i]$;
意思是:前$i$件物品中产生$j$个颜色的概率为前$(i-1)$个物品产生$j$个颜色*第$i$个物品不产生颜色的概率,加上前$(i-1)$件物品产生$(j-1)$种颜色*第i个物品产生颜色的概率。然后再用滚动数组优化成一维dp即可。
#include <bits/stdc++.h> using namespace std; const int N = 1e5+10; double p[N]; double dp[1010]; //实际上是dp[i][j],只不过下面用了滚动数组,意义是前i个物品产生j中颜色的概率 int main(){ int n,k; scanf("%d %d",&n, &k); double ans = 0; for(int i = 1; i <= n; i ++) scanf("%lf",&p[i]), ans += p[i]; dp[0] = 1; for(int i = 1; i <= n; i ++){ for(int j = k;j>=0;j--){ dp[j] = dp[j]*(1-p[i])+dp[j-1]*p[i]; }//前i个物品产生j种颜色的概率为,前i-1个物品产生 j种颜色的概率*第i个物品不产生颜色的概率加上前i-1个物品产生j-1个颜色的概率*第j个物品产生颜色的概率 } printf("%.4f %.4lf",ans,dp[k]); return 0; }