1. 程式人生 > >Fleecing the Raffle(NCPC 2016 暴力求解)

Fleecing the Raffle(NCPC 2016 暴力求解)

inpu where spl wan clas box namespace 輸出 ssi

題目:

A tremendously exciting raffle is being held, with some tremendously exciting prizes being given out. All you have to do to have a chance of being a winner is to put a piece of paper with your name on it in the raffle box. The lucky winners of the p prizes are decided by drawing p names from the box. When a piece of paper with a name has been drawn it is not put back into the box – each person can win at most one prize.

Naturally, it is against the raffle rules to put your name in the box more than once. However, it is only cheating if you are actually caught, and since not even the raffle organizers want to spend time checking all the names in the box, the only way you can get caught is if your name ends up being drawn for more than one of the prizes. This means that cheating and placing your name more than once can sometimes increase your chances of winning a prize.

You know the number of names in the raffle box placed by other people, and the number of prizes that will be given out. By carefully choosing how many times to add your own name to the box, how large can you make your chances of winning a prize (i.e., the probability that your name is drawn exactly once)?

Input:

The input consists of a single line containing two integers n and p (2 ≤ p ≤ n ≤ 106 ), where n is the number of names in the raffle box excluding yours, and p is the number of prizes that will be given away.

Output:

Output a single line containing the maximum possible probability of winning a prize, accurate up to an absolute error of 10-6.

題意:

有n個人,p個獲獎名額。遊戲規則為每個人往一個盒子中放一張帶有自己名字的紙條,然後一次性從中拿出p張這條,這p個就是獲獎的人。小明想往裏邊多放一些帶有自己名字的紙條來提高自己中獎的概率,被發現作弊的情況為,抽出的p張紙條中有兩條寫著“小明”。問在不被發現的情況下,小明通過作弊最高的獲獎率為多少。

思路:

嗯,,,,,,在隊友的啟發下,跟高中數學老師把概率這塊的知識要回來後,終於自己推出了公式如下圖(字醜不要噴啊):

技術分享圖片

圖中圈出來的兩部分的項是相等的。所以枚舉a直接上暴力大法就可以了。寫完交題,結果TLE,然後在取最大值之前輸出了一下答案,發現到達最大後後邊的值都是相等的就沒有必要計算了,直接break就ok了。

代碼:

技術分享圖片
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string.h>
#include <cstdlib>
#include <algorithm>
#include <stack>
#include <map>
#include <malloc.h>
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4 + 10;
typedef long long ll;
double m, p;

int main() {
    cin >> m >> p;
    double ans = 1.0, sum = 0.0;
    for(double k = 1; k <= m; k++) {
        ans = 1.0;
        ans = ans*(k/(m+k));
        for(double i = 0; i < p-1; i++) {
            ans *= (m - i);
            ans /= (m - i + k - 1);
        }
        if(ans > sum)
            sum = ans;
        else
            break;
    }
    sum = sum*p;
    cout << setprecision(8) << sum << endl;
    return 0;
}
/*
樣例輸入:
3 2
23 5
樣例輸出:
0.6
0.45049857550
*/
View Code

Fleecing the Raffle(NCPC 2016 暴力求解)