hdu1410 math problem combination probability log optimization

PK martial arts leader

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


Problem Description
Feng Zhiyu thought that he was very strong and wanted to be the leader of the martial arts alliance, so he challenged the current leader of the martial arts alliance with copper hydroxide. Copper hydroxide readily accepted the challenge, and the two agreed to fight on three pillars on the HDU campus on the night of the full moon next month. This PK game will definitely attract everyone in the martial arts to watch the battle, so they have found you, an economic man with potential for commercial operation, and asked you to organize this once-in-a-century battle of the century, assuming that both of them have a certain amount of HP1 , HP2.HP1 is Maple Feather, HP2 is copper hydroxide. They also have a certain attack power AP1, AP2, AP1 is Maple Feather, AP2 is copper hydroxide. When attacking, the opponent's HP reduces its own attack power, such as HP1=2 HP2=1 AP1=1 AP2=1, when copper hydroxide attacks Maple Feather, Maple Feather's HP=2 (original HP1) -1 (AP2 of copper hydroxide)=1. Now the two are dueling for many rounds. In each round, either Maple Feather attacks Copper Hydroxide, or Copper Hydroxide attacks Maple Feather. Ask Feng Zhiyu to win the victory rate of copper hydroxide to become the next martial arts leader.
 

 

Input
This question contains multiple sets of test data, each row is HP1, HP2, AP1 and AP2 (1<=HP1,HP2,AP1,AP2<=32767)
 

 

Output
Output one row for each set of data, which is the value of the probability of Feng Zhiyu winning copper hydroxide (retain 4 decimal places for the result).
 

 

Sample Input
2 1 1 1
 

 

Sample Output
75.0000
 

 

Author
Eddy

 This question is quite simple, but because of the need to optimize the accuracy, I have been pitted for an afternoon. I originally wanted to go to the gross concept class. I can learn from this question in the future combination questions. It's very good.
Ideas:
a failure requires num_a=hp1/ap2+!!(hp1%ap2) times ps. Forgot to add parentheses after !!, WA 3 times
Similarly, b failure requires num_b=hp2/ap1+!!(hp2%ap1) times
a wins, then b must fail num_b times, and we can be sure that the last time b must fail, a can fail [0, num_a-1) times
 
In this way, I can use the free combination law to do it, but it needs O(n*2) appearance, but
C(i,j) = C(i-1,,j-1)*j/i   (j=i+num_b-1) 
 
The optimal substructure is obtained, dp gets started
The probability of this question is very small, so it needs to be logized, and 0.5^x will be very small . Even if it is logized, the double precision is not enough, so it must be handled separately, and must not be handled together with the freely combined dp[i] , suffered a big loss, such as 3000 3000 1 1 , the requirement for this question is 50.0000, it is not easy to output 0.0000, and the accuracy is not enough
#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;


intmain ()
{
    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) is separated from probability, log improves accuracy 
        }
        printf("%.4lf\n",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

 

 
 

Reprinted in: https://www.cnblogs.com/EdsonLin/p/5439211.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326489059&siteId=291194637