DP学习:概率dp

1.SPOJ Favorite Dice

题意:
甩一个n面的骰子,问每一面都被甩到的次数期望是多少。

做法:
期望dp
那我们每次可能扔中已经扔过的面或者没有扔到过的面,则在第i次有2种情况:
1.扔中已经扔过的面概率:(i-1)/n,期望:E= dp(i - 1) * ((i - 1) / n)
2.扔中未扔到过的面概率:(n-(i-1)) /n,期望:E= dp(i) * ((n - (i - 1)) / n)
则状态方程:dp(i) = dp(i - 1) * ((i - 1) / n) + 1 + dp(i) * ((n - (i - 1)) / n)。
解得dp(i) = dp(i - 1) + (n / (i - 1))

点击查看代码块
/*
甩一个n面的骰子,问每一面都被甩到的次数期望是多少。
*/
#include <bits/stdc++.h>

#define ed end()
#define bg begin()
#define mp make_pair
#define pb push_back
#define v(T) vector<T>
#define all(x) x.bg,x.ed
#define newline puts("")
#define si(x) ((int)x.size())
#define rep(i,n) for(int i=1;i<=n;++i)
#define rrep(i,n) for(int i=0;i<n;++i)
#define srep(i,s,t) for(int i=s;i<=t;++i)

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 1e4+10;
const int inf = 0x7f7f7f7f;
const ll inf_ll = 1ll*inf*inf;
const int Mod = 1e9+7;
const double eps = 1e-7;

double dp[maxn];

int main(){
    int T;
    scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        int n;
        scanf("%d",&n);
        dp[1]=1.0;
        for (int i=2;i<=n;i++){
            dp[i]=dp[i-1]+((double)n / (i-1.0));
        }
        printf("%.2f\n",dp[n]);
    }
    return 0;
}

2.小A买彩票

题目描述:
小A最近开始沉迷买彩票,并且希望能够通过买彩票发家致富。已知购买一张彩票需要3元,而彩票中奖的金额分别为1,2,3,4元,并且比较独特的是这个彩票中奖的各种金额都是等可能的。现在小A连续购买了n张彩票,他希望你能够告诉他至少能够不亏本的概率是多少。

做法:
看似要求概率,实则可以进行转换成求方案数:dp[i][j]表示选第i张彩票获得j利润时候的方案数。

\(dp[i][j] = Σdp[i-1][j-k] (1<=k<=4)\)
最后求一个j>=3*n时候的方案数除以总方案数则为答案,要记得约分化简

点击查看代码块
#include <bits/stdc++.h>

#define ed end()
#define bg begin()
#define mp make_pair
#define pb push_back
#define vv(T) v(v(T))
#define v(T) vector<T>
#define all(x) x.bg,x.ed
#define newline puts("")
#define si(x) ((int)x.size())
#define rep(i,n) for(int i=1;i<=n;++i)
#define rrep(i,n) for(int i=0;i<n;++i)
#define srep(i,s,t) for(int i=s;i<=t;++i)

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 200;
const int inf = 0x7f7f7f7f;
const ll inf_ll = 1ll*inf*inf;
const int Mod = 1e9+7;
const double eps = 1e-7;

int n;
ll dp[maxn][maxn];

ll gcd(ll a,ll b){
    return b == 0 ? a : gcd(b,a%b);
}
int main(){
    cin>>n;
    if(n==0){
        puts("1/1");
        return 0;
    }
    memset(dp,0,sizeof(dp));
    rep(i,4){
        dp[1][i]=1;
    }   
    for (int i=2;i<=n;i++){
        for (int j=1;j<=i*4;j++){
            for (int k=1;k<=4;k++){
                if(j-k>=0){
                    dp[i][j]+=dp[i-1][j-k];
                }
            }
        }
    }
    ll cnt1,cnt2;
    cnt1=cnt2=0;

    for (int i=1;i<=4*n;i++){
        cnt1+=dp[n][i];
        if(i>=n*3) cnt2+=dp[n][i];
    }
    ll k = gcd(cnt1,cnt2);
    printf("%lld/%lld\n",cnt2/k,cnt1/k);
    return 0;
}
posted @ 2020-08-05 16:03  wsl_lld  阅读(222)  评论(0编辑  收藏  举报