zoukankan      html  css  js  c++  java
  • hdu1410 数学题组合概率 log优化

    PK武林盟主

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 1250    Accepted Submission(s): 303


    Problem Description
    枫之羽认为自己很强,想当武林盟主,于是找现任武林盟主氢氧化铜挑战。氢氧化铜欣然接受了挑战,两人约好于下个月的月圆之夜在HDU校园内的三根柱子上进行决战。这场PK赛肯定能吸引武林中所有人前来观战,所以他们找了有商业运作潜力的经济人你,让你来组织这场百年一见的世纪之战,假设两人都有一定的血HP1、HP2.HP1是枫之羽的,HP2是氢氧化铜的。他们也有一定攻击力AP1、AP2,AP1是枫之羽的,AP2是氢氧化铜的。当进行攻击时,对方的HP减少自己的攻击力,比如HP1=2 HP2=1 AP1=1 AP2=1,当氢氧化铜攻击枫之羽时,枫之羽的HP=2(原先的HP1)-1(氢氧化铜的AP2)=1。现在两个人对决很多回合,每回合不是枫之羽攻击氢氧化铜,就是氢氧化铜攻击枫之羽。求枫之羽能赢氢氧化铜成为下任武林盟主的的胜率。
     
    Input
    该题含有多组测试数据,每行为HP1,HP2,AP1和AP2 (1<=HP1,HP2,AP1,AP2<=32767)
     
    Output
    每组数据输出一行,为枫之羽赢氢氧化铜概率的值 (结果保留4位小数).
     
    Sample Input
    2 1 1 1
     
    Sample Output
    75.0000
     
    Author
    Eddy

     这题挺简单的吧,不过因为要精度优化,坑了我一下午,本来想去上毛概课的,以后组合题可以借鉴这道题吧,挺好的
    思路:
    a失败需要num_a=hp1/ap2+!!(hp1%ap2)次 ps.忘了在!!后面加括号,WA了3次
    同理,b失败需要num_b=hp2/ap1+!!(hp2%ap1)次
    a胜利,则b一定要失败num_b次,而且我们可以确定最后一次一定是b失败,a可以失败[0,num_a-1)次
     
    这样我用就可用自由组合定律做了,不过需要O(n*2)的样子,但是
    C(i,j) = C(i-1,,j-1)*j/i   (j=i+num_b-1) 
     
    得到了最优子结构,dp上手
    本题概率非常小,所以需要log化,还有一点0.5^x会非常小,即使log化,double精度也不够了,所以要单独处理,千万不要和自由组合的dp[i]放在一起处理,吃了大亏,比如3000 3000 1 1 , 本题要求是50.0000 不容易就会输出0.0000了,精度不够的问题
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <cstdlib>
    #include <string>
    #include <algorithm>
    #include <stack>
    #include <queue>
    
    const int inf = (1<<31)-1;
    const int MAXN = 4e4;
    using namespace std;
    
    
    int main()
    {
        int hp1,ap1,hp2,ap2;
        int a,b;
        while(scanf("%d%d%d%d",&hp1,&hp2,&ap1,&ap2)!=EOF){
            double sum,temp;
            a = hp1/ap2 + !!(hp1%ap2);
            b = hp2/ap1 + !!(hp2%ap1);
            sum = pow(0.5,b);
            temp = 0.0;
            for(int i=1;i<a;i++){
                temp += log10((i+b-1)*1.0)-log10(1.0*i);
    
                sum += pow(10,temp+(b+i)*log10(0.5)); //C(i,j)与概率分离处理,log提高精度
            }
            printf("%.4lf
    ",sum*100.0);
        }
        return 0;
    }
    /*
    15 18 12 1
    99.9741
    1 1 1
    1
    50.0000
    2 2 2 2
    50.0000
    3 3 3 3
    50.0000
    18 19 100 1
    99.9996
    18 19 1 100
    0.0002*/
    View Code
     
     
    在一个谎言的国度,沉默就是英雄
  • 相关阅读:
    属性序列化自定义与字母表排序-JSON框架Jackson精解第3篇
    URL及日期等特殊数据格式处理-JSON框架Jackson精解第2篇
    JSON数据处理框架Jackson精解第一篇-序列化与反序列化核心用法
    开源项目-跨项目及操作系统的通用代码生成器,解放您的双手
    图解并发与并行-分别从CPU和线程的角度理解
    8成以上的java线程状态图都画错了,看看这个-图解java并发第二篇
    面霸告诉你这些技术面试的非技术性经验,让你的面试成功率显著提升
    List集合对象去重及按属性去重的8种方法-java基础总结系列第六篇
    图解进程线程、互斥锁与信号量-看完不懂你来打我
    总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
  • 原文地址:https://www.cnblogs.com/EdsonLin/p/5439211.html
Copyright © 2011-2022 走看看