第一场-F-Fleecing the Raffle

题目链接:点击打开链接

(一)题面:

Description

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

There will be several test cases. Each case consists of a single line containing two integers n and p ( 2pn1062≤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.

Sample Input

3 2
23 5

Sample Output

0.6
0.45049857550

(二)题目大意:

现在一个抽奖箱里面有n张不同的卡片,需要从中抽取p张。现在你想在抽奖箱中加入k张卡片(代表你),你需要确定一个k,使得抽到你且仅抽到你一次的概率最大。并输出该最大概率。


(三)解题思路:

  1. 数学题,写表达式,求最值即可。
  2. 不难得到加入k张卡片后,所求概率为:
    P(k)=C(k,1)*C(n,p-1)/C(n+k,p)
    =k*C(n,p-1)/C(n+k,p)
    =k*[n!/((p-1)!*(n-p+1)!)]*[(p!)*(n+k-p)!/(n+k)!]
    =k*p*n!*(n+k-p)!/((n-p+1)!*(n+k)!);
  3. P(k+1)/P(k)=(k+1)*(n+k-p+1)/((n+k+1)*k),令P(k+1)/P(k)>1,得:k<(n-p+1)/(p-1),故使概率最大时,K=floor((n-p+1)/(p-1))+1;

(四)具体代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#define LL long long
using namespace std;
double get(double x,double y,int k){
    double res=1.0;
    for(int i=0;i<=k-2;i++){
        res=res*(x-i)/(y-i);
    }
    res/=y-k+1;
    return res;
}
int main(){
    freopen("in.txt","r",stdin);
    LL n,p;
    while(cin>>n>>p){
        int k=(n-p+1)/(p-1);
        double ans=p*1.0*(k+1)*get(n,n+k+1,p);
        printf("%.10lf\n",ans);
    }
    return 0;
}


(五)总结:
  1. 实际写的时候,没有想到求最值点,但是猜得到应该存在最值点,所以当时直接从1开始遍历,直到概率值变小就退出,本以为会T的,结果最后跑得还挺快的。估计数据不卡吧。
  2. 数学题目需要多推敲。

猜你喜欢

转载自blog.csdn.net/xbb224007/article/details/79983891