[cattle guest] practice match 26 - B Fireworks (probability DP)

Title Link

Question meaning: Xiao a has a fireworks. Each fireworks represents different colors. For the first fireworks, it has a probability to light them. Now Xiao a wants to light them. He wants to know the expected number of colors and the probability of producing exactly one color.

Idea: probability DP.
Let's look at the table below. It's a case of n being 3 and k being 2.

i\dp\j 0 1 2
0 1 0 0
1 1−p11−p1 p1p1 0
2 (1−p1)∗(1−p2)(1−p1)∗(1−p2) (1−p1)∗p2+p1∗(1−p2)(1−p1)∗p2+p1∗(1−p2) p1∗p2p1∗p2
3 (1−p1)∗(1−p2)∗(1−p3)(1−p1)∗(1−p2)∗(1−p3) (1−p1)∗(1−p2)∗p3+(1−p1)∗p2∗(1−p3)+p1∗(1−p2)∗p3(1−p1)∗(1−p2)∗p3+(1−p1)∗p2∗(1−p3)+p1∗(1−p2)∗p3 (1−p1)∗p2∗p3+p1∗(1−p2)∗p3+p1∗p2∗(1−p3)(1−p1)∗p2∗p3+p1∗(1−p2)∗p3+p1∗p2∗(1−p3)

It can be seen that for the first i fireworks, the probability of exactly j fireworks is only related to the probability of the first i-1 fireworks, just j or j-1 fireworks.

Let DP[i][j] denote the probability that the first I fireworks just exploded j, then the DP equation can be obtained

{DP[i][j]=DP[i−1][j]∗(1−pi)+DP[i−1][j−1]∗piDP[0][0]=1{DP[i][j]=DP[i−1][j]∗(1−pi)+DP[i−1][j−1]∗piDP[0][0]=1

AC Code:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int, int> pii;
inline int read(){int r=0;char c=getchar();while(c<'0'||c>'9') {c=getchar();}while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}return r;}
inline ll readll(){ll r=0;char c=getchar();while(c<'0'||c>'9') {c=getchar();}while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}return r;}
const double eps = 1e-8;
const double PI = acos(-1.0);
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int MAXN = 1e5;
const int MAXM = 1e5;

double dp[MAXN][233];
int main(int argc, char const *argv[])
{
    int n, k;
    double p, ans = 0;
    cin >> n >> k;
    dp[0][0] = 1;
    for(int i=1; i<=n; ++i){
        cin >> p;
        ans += p;
        dp[i][0] = dp[i-1][0]*(1.0-p);
        for(int j=1; j<=k;++j){
            dp[i][j] = dp[i-1][j]*(1.0-p)+dp[i-1][j-1]*p;
        }
    }
    printf("%.4lf\n%.4lf", ans, dp[n][k]);
    return 0;
}

The time complexity of this DP equation can not be optimized, but the space complexity can also be optimized from n*k to K.
We use DP[i] to express the probability that I fireworks are just set off after they have been set off for a while, and reuse DP array.

However, we need to pay attention to one thing: when we update DP, we need to update from the back to the front, because the update from the front to the back will overwrite the DP value of the previous layer used in the later update.

AC Code:

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
typedef long long ll;
typedef pair<int, int> pii;
inline int read(){int r=0;char c=getchar();while(c<'0'||c>'9') {c=getchar();}while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}return r;}
inline ll readll(){ll r=0;char c=getchar();while(c<'0'||c>'9') {c=getchar();}while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}return r;}
const double eps = 1e-8;
//const double PI = acos(-1.0);
const ll INFLL = 0x3f3f3f3f3f3f3f3f;
const int INF = 0x3f3f3f3f;
const int mod = 1e9+7;
const int MAXN = 1e5;
const int MAXM = 1e5;

double dp[233];
int main(int argc, char const *argv[])
{
    int n, k;
    double p, ans = 0;
    cin >> n >> k;
    dp[0] = 1;
    for(int i=1; i<=n; ++i){
        cin >> p;
        ans += p;
        for(int j=k; j>=0; --j){
            dp[j] = dp[j]*(1.0-p)+dp[j-1]*p;
        }
    }
    printf("%.4lf\n%.4lf", ans, dp[k]);
    return 0;
}

Posted by pauper_i on Tue, 31 Dec 2019 22:49:06 -0800