hdu4652_Dice_概率DP

题目大意

给以m个面的色子,求:
0.多次抛掷中最后n次点数相同的抛掷次数的期望
1. 多次抛掷中最后n次点数各不相同的抛掷次数的期望

思路

0.概率DP的倒推求法,设dp[i]为最后i次点数相同直到最后n次点数相同还需要抛掷的次数的期望
dp[i] = 1 / m * dp[i + 1] + (1 - 1 / m) * dp[1] + 1
边界:dp[n] = 0
可用等比数列求和公式求通项

1. 设dp[i]为最后i次点数不同直到最后n次点数相同还需要抛掷的次数的期望
dp[i] = (1 - i / m) * dp[i + 1] + 1 / m * (dp[1] + dp[2] + ... + dp[i]) + 1  (i <= n- 2 && i >= 1)
dp[n - 1] = 1 / m * (dp[1] + dp[2] + ... + dp[n - 1]) + 1

相邻的式子相减
dp[i + 1] - dp[i] = (1 - (i + 1) / m) * (dp[i + 2] - dp[i + 1])   (i >= 1 && i <= n - 3)
又dp[1] - dp[2] = 1 / (1 - 1 / m)
dp[1] = 1 / (1 - 1 / m) + 1 / [ (1- 1 / m) * (1 - 2 / m) ] + ... + 1 / [ (1- 1 / m) * (1 - 2 / m) * ... * (1 - (n - 1) / m) ]


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))

using namespace std;
double multi(double a, int t)
{
    int flag = 0;
    if (t < 0)
    {
        t = -t;
        flag = 1;
    }
    double ans = 1;
    while (t)
    {
        if (t & 1)
        {
            ans *= a;
        }
        a *= a;
        t >>= 1;
    }
    if (flag)
        ans = 1 / ans;
    return ans;
}
double solve(int m, int n)
{

    if (n == 1)
        return 1;
    
    double tmp = multi(m, 1 - n);
    return (1 - tmp) / (1 - (double)1 / m) / tmp + 1;

}
double solve1(int m, int n)
{
    if (n == 1)
        return 1;
    double ans = 0, tmp = 1;
    for (int i = 1; i <= n - 1; i++)
    {
        tmp /= 1 - (double)i / m;
        ans += tmp;

    }
    return ans + 1;



}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE
    int t, no, m, n;
    //cout << multi(2, -11) <<endl;
    while (scanf("%d", &t) != EOF && t)
    {
        while (t--)
        {
            scanf("%d %d %d", &no, &m, &n);
            if (!no)
            {
                printf("%.9f\n", solve(m, n));
            }
            else
                printf("%.9f\n", solve1(m, n));

        }
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/Anna__1997/article/details/79558950