zoukankan      html  css  js  c++  java
  • [codeforces464D]World of Darkraft

    D. World of Darkraft - 2

    time limit per test 2 seconds

    memory limit per test 256 megabytes

    input standard input

    output standard output

    Roma found a new character in the game "World of Darkraft - 2". In this game the character fights monsters, finds the more and more advanced stuff that lets him fight stronger monsters.

    The character can equip himself with k distinct types of items. Power of each item depends on its level (positive integer number). Initially the character has one 1-level item of each of the k types.

    After the victory over the monster the character finds exactly one new randomly generated item. The generation process looks as follows. Firstly the type of the item is defined; each of the k types has the same probability. Then the level of the new item is defined. Let's assume that the level of player's item of the chosen type is equal to t at the moment. Level of the new item will be chosen uniformly among integers from segment [1; t + 1].

    From the new item and the current player's item of the same type Roma chooses the best one (i.e. the one with greater level) and equips it (if both of them has the same level Roma choses any). The remaining item is sold for coins. Roma sells an item of level x of any type forx coins.

    Help Roma determine the expected number of earned coins after the victory over n monsters.

    Input

    The first line contains two integers, n and k (1 ≤ n ≤ 105; 1 ≤ k ≤ 100).

    Output

    Print a real number — expected number of earned coins after victory over n monsters. The answer is considered correct if its relative or absolute error doesn't exceed 10 - 9.

    Examples

    input

    1 3

    output

    1.0000000000

    input

    2 1

    output

    2.3333333333

    input

    10 2

    output

    15.9380768924

    题解:

    这道题真的是好题啊……

    我们不难发现,每一种武器的金币贡献都是相互独立的,因此我们只需要处理一种武器的情况,最后*k即可

    那么我们考虑转移,设dp数组为f[i][j],表示带着等级为j的武器打i只怪,能得到的期望收益,

    那么显然f[0][j]均为0,我们最终的目标就是求f[n][1]

    接下来考虑转移,每一次打怪有1/k的概率掉落这种装备,有(k-1)/k概率不掉落,就无法从这种装备上得到收益

    因此f[i][j]=(期望金币收益)/k+(k-1)*f[i-1][j]/k

    而期望金币收益中,有1/(j+1)概率掉落高级装备,j/(j+1)概率掉落低级装备

    因此 期望金币收益=(f[i-1][j+1]+j)/(j+1)+(f[i-1][j]+(j+1)/2)*j/(j+1)

    其中(j+1)/2为低级装备的期望收益(平均数)

    因此综上,f[i][j]=((f[i-1][j+1]+j)/(j+1.0)+j*(f[i-1][j]+(j+1.0)/2.0 )/(j+1.0))/(k*1.0)+(k-1)*f[i-1][j]/(k*1.0);

    但是,这样是一个O(n2)的算法,时间超限,空间也可能超限,因此我们考虑优化

    首先显然,f数组可以滚动,解决了空间问题

    接着,我们发现1s内108=105*1000,因此我们第二次循环变成1000次以内就好了

    那么,我们可不可以在n太大时把第二层n变成一个小数吗?这是正确的吗?

    我们可以发现,如果j很大的话,装备升级的可能就很小

    如果是f[i][i+1],总的概率是(1/k)i*1/(n+1)!,而题目中说“The answer is considered correct if its relative or absolute error doesn't exceed 10 - 9.”

    因此这样小的数据我们完全可以扔掉不要

    事实上,我们只要枚举j从1到1000左右即可,这样复杂度就被降到了1s以内,这样我们就解决了本题

    代码见下:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    int n,k;
    double f[2][850];
    int main()
    {
        scanf("%d%d",&n,&k);
        int t=min(n,800);
        int now=1;
        for(int i=1;i<=n;i++,now^=1)
            for(int j=t;j;j--)
                f[now][j]=((f[now^1][j+1]+j)/(j+1.0)+j*(f[now^1][j]+(j+1.0)/2.0 )/(j+1.0))/(k*1.0)+(k-1)*f[now^1][j]/(k*1.0);
        printf("%.10lf",k*f[now^1][1]);
    }
  • 相关阅读:
    10月17日学习日志
    10月10日学习日志
    10月15日学习日志
    ERP临时汇报打草稿
    锁定字段的几个方法
    Mvc model验证总结
    Html5 WebSocket详细介绍
    C#连接Oracle数据库的方法(System.Data.OracleClient、Oracle.DataAccess.Client也叫ODP.net、Oracle.ManagedDataAccess.dll)
    MVC Ajax调用Action时OnActionExecuting RedirectResult 无法跳转的处理办法
    C#调用存储过程中事务级临时表返回DataTable列乱序解决办法
  • 原文地址:https://www.cnblogs.com/LadyLex/p/7248195.html
Copyright © 2011-2022 走看看