zoukankan      html  css  js  c++  java
  • HDU 4652 Dice:期望dp(成环)【错位相减】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4652

    题意:

      给你一个有m个面的骰子。

      两种询问:

        (1)"0 m n": “最后n次点数均相同”的投掷次数期望。

        (2)"1 m n": “最后n次点数各不相同”的投掷次数期望。

     

    题解:

      表示状态:

        dp[i] = expectation (当前已经有i个点数相同/不相同)

     

      找出答案:

        ans = dp[0]

     

      如何转移:

      一、都相同

        (1)dp[i] = dp[i+1]/m + dp[1]*(1-1/m) + 1 (要么与前面相同,要么不同)

        (2)dp[i+1] = dp[i+2]/m + dp[1]*(1-1/m) + 1 (为了错位相减消去后面的dp[1],令i = i+1)

        (1)-(2)得:

          dp[i] - dp[i+1] = (dp[i+1] - dp[i+2])/m

        设d[i] = dp[i] - dp[i+1],有d[i+1]= dp[i]*m (d[i]可递推)

        则:dp[0] - dp[n] = sigma(d[0 to n-1]) (前后两项相消)

        又因为:dp[n] = 0

        所以:dp[0] = sigma(d[0 to n-1]),枚举求和即可。

     

      二、都不同

        (1)dp[i] = dp[i+1]*(m-i)/m + dp[i]/m + dp[i-1]/m +...+ dp[1]/m + 1 (要么与之前均不同,要么与第n,n-1,n-2...1位相同)

        (2)dp[i+1] = dp[i+2]*(m-i-1)/m + dp[i+1]/m + dp[i]/m +...+ dp[1]/m + 1 (令i = i+1,错位相减)

        (1)-(2)得:

          dp[i] - dp[i+1] = (dp[i+1] - dp[i+2])*(m-i-1)/m

        设d[i] = dp[i] - dp[i+1],有d[i+1]= dp[i]*m/(m-i-1) (d[i]可递推)

        则:dp[0] - dp[n] = sigma(d[0 to n-1])

        同一中:dp[0] = sigma(d[0 to n-1]) 即为答案。

     

    AC Code:

      1 // PROB 1: is the same
      2 //
      3 // state expresssion:
      4 // dp[i] = expectation
      5 // i: the same numbers
      6 //
      7 // find the answer:
      8 // ans = dp[1] + 1
      9 //
     10 // transferring:
     11 // dp[i] = dp[i+1]/m + dp[1]*(1-1/m) + 1
     12 // dp[i+1] = dp[i+2]/m + dp[1]*(1-1/m) + 1
     13 // dp[i] - dp[i+1] = dp[i+1]/m - dp[i+2]/m
     14 // dp[i] - dp[i+1] = (dp[i+1] - dp[i+2])/m
     15 // dp[i+1] - dp[i+2] = (dp[i] - dp[i+1])*m
     16 // d[0] = dp[0] - dp[1] = 1
     17 // dp[0] + dp[n] = sigma(d[0 to n-1])
     18 // dp[0] = sigma(d[0 to n-1])
     19 //
     20 //
     21 // PROB 2: is different
     22 //
     23 // state expression:
     24 // dp[i] = expectation
     25 // i: different numbers
     26 //
     27 // find the answer:
     28 // ans = dp[1] + 1
     29 //
     30 // transferring:
     31 // dp[i] = dp[i+1]*(m-i)/m + dp[i]/m + dp[i-1]/m +...+ dp[1]/m + 1
     32 // dp[i+1] = dp[i+2]*(m-i-1)/m + dp[i+1]/m + dp[i]/m +...+ dp[2]/m + dp[1]/m + 1
     33 // dp[i] - dp[i+1] = dp[i+1]*(m-i)/m - dp[i+2]*(m-i-1)/m - dp[i+1]/m
     34 // dp[i] - dp[i+1] = (dp[i+1] - dp[i+2])*(m-i-1)/m
     35 // dp[i+1] - dp[i+2] = (dp[i] - dp[i+1])*m/(m-i-1)
     36 // d[0] = dp[0] - dp[1] = 1
     37 // dp[0] + dp[n] = sigma(d[0 to n-1])
     38 // dp[0] = sigma(d[0 to n-1])
     39 #include <iostream>
     40 #include <stdio.h>
     41 #include <string.h>
     42 #define MAX_N 1000005
     43 
     44 using namespace std;
     45 
     46 int n,m,p,t;
     47 double ans;
     48 double dp[MAX_N];
     49 
     50 void read()
     51 {
     52     cin>>p>>m>>n;
     53 }
     54 
     55 void cal_dp_same()
     56 {
     57     // dp[i+1] - dp[i+2] = (dp[i] - dp[i+1])*m
     58     // dp[0] = sigma(d[0 to n-1])
     59     double d=1;
     60     ans=0;
     61     for(int i=0;i<n;i++)
     62     {
     63         ans+=d;
     64         d*=m;
     65     }
     66 }
     67 
     68 void cal_dp_dif()
     69 {
     70     // dp[i+1] - dp[i+2] = (dp[i] - dp[i+1])*m/(m-i-1)
     71     // dp[0] = sigma(d[0 to n-1])
     72     double d=1;
     73     ans=0;
     74     for(int i=0;i<n;i++)
     75     {
     76         ans+=d;
     77         d*=m/(m-i-1.0);
     78     }
     79 }
     80 
     81 void solve()
     82 {
     83     if(p==0) cal_dp_same();
     84     else cal_dp_dif();
     85 }
     86 
     87 void print()
     88 {
     89     printf("%.9f
    ",ans);
     90 }
     91 
     92 int main()
     93 {
     94     while(cin>>t)
     95     {
     96         while(t--)
     97         {
     98             read();
     99             solve();
    100             print();
    101         }
    102     }
    103 }

    dp[i] = dp[i+1]*(m-i)/m + dp[i]/m + dp[i-1]/m +...+ dp[1]/m + 1

  • 相关阅读:
    HDU 6984
    洛谷 P6776
    C语言 error C4996: This function or variable may be unsafe
    C语言 sizeof 函数
    C语言 strlen 函数
    C语言 char 字符串
    C语言 goto 语句
    C语言 switch 语句
    C语言 do while 和 while 循环
    C语言 while 循环
  • 原文地址:https://www.cnblogs.com/Leohh/p/7583627.html
Copyright © 2011-2022 走看看