• HDU 5236 Article 期望


    题意:

    你现在要打(n)个字符,但是程序随时可能会崩溃。
    你可以在恰当的时机按下 (Ctrl-S)键,崩溃后,会从最后一次保存的情况继续开始打字。
    具体是这样的:

    • 在每个第(i-0.1s(i>0))的时候,程序崩溃的概率为(p)
    • 在每个第(is(i geq 0))的时候,你可以一口气按下(x)个键来存盘
    • 在每个第(i+0.1s(i geq 0))的时候,你可以按下一个键来打字

    求采取最优策略下,打完这(n)个字符,并且最后存盘,总按键次数的期望。

    分析:

    先不考虑可以存盘的情况,设(d(i))为打印(i)个字符按键次数的期望。
    有递推公式:(d(i)=d(i-1)+1+p cdot d(i))
    当你打印出前(i-1)个字符,刚刚打完第(i)个的时候:

    • 有概率(p)会崩掉,这时候要重新开始,还需要的按键数的期望为(d(i))
    • 有概率(1-p)没崩,打印完成了

    化简一下得到:(d(i)=frac{1}{1-p}d(i-1)+frac{1}{1-p})

    然后再考虑存盘的情况,我们枚举存了(x)次盘,也就是把这(n)个字符分为(x)段,每打完一段就存一次盘。
    由于(frac{1}{1-p}>1),可以看出(d(n))是指数型增长的,所以就尽可能均匀地把(n)个字符分成(x)段。
    或者也可以求一下(d(n))的通项公式为:(d(n)=frac{1}{p(1-p)^n}-frac{1}{p})来验证。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 100000 + 10;
    const double INF = 1e20;
    double d[maxn];
    
    int main()
    {
        int T; scanf("%d", &T);
        for(int kase = 1; kase <= T; kase++) {
            int n, x; double p;
            scanf("%d%lf%d", &n, &p, &x);
            
            d[0] = 0;
            for(int i = 1; i <= n; i++) d[i] = (d[i - 1] + 1.0) / (1.0 - p);
    
            double ans = INF;
            for(int i = 1; i <= n; i++) {
                int k = n / i, r = n % i;
                ans = min(ans, r*d[k+1] + (i-r)*d[k] + i*x);
            }
    
            printf("Case #%d: %.6f
    ", kase, ans);
        }
    
        return 0;
    }
    
  • 相关阅读:
    给列表单元格加背景色
    Log4j最简入门及实例
    MySQL 按指定字段自定义列表排序
    MySQL逗号分割字段的列转行
    利用MySQL统计一列中不同值的数量方法示例
    使用docx4j编程式地创建复杂的Word(.docx)文档
    向Docx4j生成的word文档中添加布局--第二部分
    向Docx4j生成的word文档添加图片和布局--第一部分
    使用Docx4j创建word文档
    [简单]docx4j常用方法小结
  • 原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/4943113.html
Copyright © 2020-2023  润新知