zoukankan      html  css  js  c++  java
  • 期望dp

    期望DP

    • 数学期望 P=Σ(每一种状态的价值*对应的概率
    • E(aX+bY)=aE(x)+bE(y)E(aX+bY)=aE(x)+bE(y)

    数学期望的dp[x]一般表示到了x这一状态还差多少,最后答案是dp[0]

    期望DP步骤一般是先推数学公式,再找递推关系

    1   Help Me Escape zoj3640(入门)

    Now Cain is unexpectedly trapped in a cave with N paths. Due to LORD's punishment, all the paths are zigzag and dangerous. The difficulty of the ith path is ci.

    Then we define f as the fighting capacity of Cain. Every day, Cain will be sent to one of the N paths randomly.

    Suppose Cain is in front of the ith path. He can successfully take ti days to escape from the cave as long as his fighting capacity f is larger than ci. Otherwise, he has to keep trying day after day. However, if Cain failed to escape, his fighting capacity would increase ci as the result of actual combat. (A kindly reminder: Cain will never died.)

    As for ti, we can easily draw a conclusion that ti is closely related to ci. Let's use the following function to describe their relationship:

     

    After D days, Cain finally escapes from the cave. Please output the expectation of D.

    Input

    The input consists of several cases. In each case, two positive integers N and f (n ≤ 100, f ≤ 10000) are given in the first line. The second line includes N positive integers ci (ci ≤ 10000, 1 ≤ i ≤ N)

    Output

    For each case, you should output the expectation(3 digits after the decimal point).

    Sample Input

    3 1

    1 2 3

    Sample Output

    6.889

    这是我做的第一个期望题目!这题只要清楚期望计算的公式,括号别括错就行了。f[i]表示攻击力为i的期望天数,详见代码E(aX+bY)=aE(x)+bE(y)E(aX+bY)=aE(x)+bE(y)*

    E(XY)=E(X)+E(Y)

    var
    dp:array[0..200005] of double;
    c:array[0..200005]of longint;
    n,x,i:longint;
    
     function solve(f:longint):double;
      var i:longint;
      begin
       if dp[f]>0 then exit(dp[f]);
        dp[f]:=0;
        for i:=1 to n do
           if f>c[i]{you wrong here} then
           begin
             dp[f]:=dp[f]+trunc(((1+sqrt(5))/2)*sqr(c[i]))/n; //注意向下取整,打的过,直接天数算出来+原来期望天数*
           end
                else dp[f]:=dp[f]+(1+solve(f+c[i]))/n;//1 代表花费一天+提升之后所需期望天数
    
          exit(dp[f]);
      end;
    begin
    while not eof do
     begin
       readln(n,x);
       for i:=1 to n do read(c[i]);
       fillchar(dp,sizeof(dp),0);
        writeln(solve(x):0:3);
       end;
    end.

    2  Race to 1 Again

    Rimi learned a new thing about integers, which is - any positive integer greater than 1 can be divided by its divisors. So, he is now playing with this property. He selects a number N. And he calls this D.

    In each turn he randomly chooses a divisor of D (1 to D). Then he divides D by the number to obtain new D. He repeats this procedure until D becomes 1. What is the expected number of moves required for N to become 1.

    Input

    Input starts with an integer T (≤ 10000), denoting the number of test cases.

    Each case begins with an integer N (1 ≤ N ≤ 105).

    Output

    For each case of input you have to print the case number and the expected value. Errors less than 10-6 will be ignored.

    Sample Input

    3

    1

    2

    50

    Sample Output

    Case 1: 0

    Case 2: 2.00

    Case 3: 3.0333333333

    题解:dp[i]表示到从i除到1的期望步数

          由期望定义可得dp[i]=dp[1]+dp[S2]+dp[S3]…+dp[i]+c/c

        (S1~sn 表示i的因数,+c是因为每次走一步期望值+1,总的就是+c了),然后你会发现,这个等式中两边都有d[i],这样是不能进行递推的,所以要进行等式化简,这样就是一个数学问题了。将dp[i]从右边提出来就是dp[i]/c,移到左边,

     

    最后化简为

    ( (c - 1) / c ) * d[i] =  ( d[1] + d[S2] + d[S3] + d[S4] ..... + d[Sc- 1]  + c) / c;

    那么d[i]就等于所有因子的期望和加上c再除以c-1

     

    上代码

     

    上代码
    var
    dp:array[0..100050]of double;
    ans:double;
    i,x,maxn,num,j,t:longint;
     begin
      for i:=2 to 100010 do
       begin
        maxn:=trunc(sqrt(i));ans:=0;num:=0;
         for j:=1 to maxn do
          begin
           if i mod j=0 then
            begin
             inc(num);
             ans:=dp[j]+ans;
              if i div j<>j then
               begin
                inc(num);
                ans:=ans+dp[i div j];
               end;
            end;
    
          end;
          dp[i]:=(ans+num)/(num-1);
         // if i=51 then break;
        //  writeln(i,' ',dp[i]:0:3);
       end;
     readln(t);
     for i:= 1 to t do
    begin
     readln(x);
     writeln('Case ',i,': ',dp[x]:0:6);
    end;、
    end.

     

     

    NOIP2018 rp++
  • 相关阅读:
    改变Edit的光标(使用CreateCaret,ShowCaret和LoadBitmap三个API函数)
    浅析Delphi Container库(有开源的DCLX)
    Delphi接口的底层实现(接口在内存中仍然有其布局,它依附在对象的内存空间中,有汇编解释)——接口的内存结构图,简单清楚,深刻 good
    Asp.Net在多线程环境下的状态存储问题
    C#程序中注释过多的8条理由
    CentOS 6.4 编译安装LLVM3.3,Clang和Libc++
    Microsoft 2013校园招聘笔试题及解答
    代码契约CodeContract(八)
    T-SQL 临时表、表变量、UNION
    BST&AVL&红黑树简单介绍
  • 原文地址:https://www.cnblogs.com/brilliant107/p/9471200.html
Copyright © 2011-2022 走看看