算法問題——生日悖論


問題:

一個屋子里人數必須要達到多少人,才能使其中兩人生日相同的機會達到50%?

為了回答這個問題,設:

1、設k是屋子里的總人數,對每一個人進行編號,則編號為1,2,3···k

2、設所有年份都是365天,最大天數n=365

3、bi表示第i個人的生日天數,所以1<=bi<=360,1<=i<=k

 

public class Main {
    /**
     * 第i個人的生日正好在“第r天的概率”為:
     *
     * P{bi=r} = 1/n
     */

    /**
     * 第i個人和第j個人的生日,“都落在第r天的概率”為:
     *
     * P{bi=r且bj=r} = P{bi=r}*P{bj=r} = (1/n)^2
     */

    /**
     * 第i個人和第j個人的生日,“都落在同一天的概率”為?
     * 此處的落在同一天並沒有指定落在那一天,所以可以都是第1天或者都是第二天或者·····
     *
     * P{bi=bj}
     * = P{bi=1}*P{bj=1} + P{bi=2}*P{bj=2}+···+P{bi=n}*P{bj=n}
     * = (1/n)^2 + (1/n)^2 + ···+ (1/n)^2
     * = 1/n
     */

    /**
     * 原問題是:找到“至少有兩個人生日相等”
     * 換句話說就是:1減去所有人生日都互不相同的概率。
     * 所以接下來就要找到“所有人生日都互不相同的概率”
     *
     * 設:
     * 1、有k個人,這k個人生日都互不相同的事件為:Bk
     * 2、那么k個人生日都互不相同的事件的概率就為:P{Bk}
     * 3、有一個人i,有多個人1-j,其中j<i(也就是說那多個人的編號從1到j,且j編號還小於i編號)
     *      則這個第i個人和1-j個人的生日不相同的事件為:Ai
     *      (即:i與1的生日不同,且i與2的生日不同···且i與j的生日不同。
     *       注意:此處1-j個人之間生日是否不同並沒有做強制規定)
     * 4、這個第i個人和1-j個人的生日不相同的事件的概率為P{Ai}
     *
     * 由此我們就可推出:
     * Bk = A1 * A2 * A3 *···* Ak
     * 因為:
     * Bk指的是k個人中,“兩兩”生日不等的事件。
     * A1指的是,1個人時,“兩兩”生日不等的事件。
     * A2指的是,第2個人和第1個人生日不等的事件。
     * A3指的是,第3個人和第1個人生日不等、且第3個人和第2個人生日不等。
     * A4指的是,第4個人和第1個人生日不等、且第4個人和第2個人生日不等。第4個人和第3個人生日不等。
     * ·····
     * 所以A1到Ak所有事件都發生的情況下,就是Bk這個事件。
     *
     * 轉換成概率就是:
     * P{Bk} = P{A1} * P{A2} * P{A3} *···* P{Ak}
     *
     * 此時我們再從另一種角度想一下這個問題,
     * B(k-1)指的是(k-1)個人中,“兩兩”生日不等的事件。
     * 這B(k-1)事件意味着第1個人到第(k-1)個人的生日“已經互不相等了”,
     * 此時如果我們要“加上第k個人”,且“還是要他們所有人生日互不相等(即達到事件Bk)”,
     * 則只需要滿足“第k個人的生日與第1人生日不同、且與第2人生日不同···且與第(k-1)人生日不同”這個事件即可。
     * (即只需要滿足第k與第1到第k-1不同,而B(k-1)表示“第1到第k-1”已經兩兩互不相同了)
     * 轉換成公式則為:
     * Bk = B(k-1) * Ak
     *
     * 由上一個思考角度繼續思考,
     * 根據這個公式:Bk = B(k-1) * Ak,可知:
     * 這(k-1)個人各有各的生日,且互不重復,也就是說,一年365天里,他們的生日占了其中的(k-1)天。
     * Ak事件如果要達成,則第k個人的生日“不能是這(k-1)天中的任意一天”。
     * 那么Ak事件(即第k人生日與這(k-1)人生日都不相等)的概率就是:(n-(k-1))/n,(k的生日必須是這(k-1)天以外的某一天)。
     * 即:P{Ak} = (n-(k-1))/n
     *
     * 綜上所述,我們能得到以下公式:
     * P{Bk}
     * = P{B(k-1)} * P{Ak}
     * = P{B(k-2)} * P{A(k-1)} * P{Ak}
     * = P{B(k-3)} * P{A(k-2)} * P{A(k-1)} * P{Ak}
     * ·····
     * = P{A1} * P{A2} * P{A3} *···*  P{A(k-1)} * P{Ak}
     * = 1 * ((n-(1))/n) * ((n-(2))/n) *···* ((n-(k-2))/n) * ((n-(k-1))/n)
     * = 1 * (1-(1/n)) * (1-(2/n)) *···* (1-((k-2)/n)) * ((1-((k-1)/n))
     */

    /**
     *
     * 由原題“生日相同的機會達到50%”,
     * 所以:1-P{Bk} >=50%,即:P{Bk} <= 1/2
     *
     * 下面就是使用一些數學知識求解了:
     * 根據不等式:1+x<=e^x ,將“-((k-1)/n)”看成不等式中的x,得:
     * P{Bk} <= e^(-(1/n)) *···* e^(-((k-1)/n))
     * P{Bk} <= e^((-k*(k-1))/2n)
     * e^((-k*(k-1))/2n) <= 1/2     (原題目要求)
     *
     * 將n=365時,
     * 解得:k>=23
     * 所以,一個屋子里人數必須要達到23人,才能使其中兩人生日相同的機會達到50%
     */

    public static void main(String[] arg){
        int sum_day = 365;

        int sum_people = birth_paradox(sum_day);

        System.out.println("當一年有"+sum_day+"天時");
        System.out.println("一個屋子里人數必須要達到"+sum_people+"人,才能使其中兩人生日相同的機會達到50%");
    }

    /**
     * 當一年有sum_day天時,
     * 一個屋子里人數必須要達到多少人,才能使其中兩人生日相同的機會達到50%
     * @param sum_day 一年的總天數
     * @return 至少得有多少人,才能達到要求
     */
    public static int birth_paradox(double sum_day){
        //所需總人數
        int sum_people;

        //初始為P{A1}=1
        double Pb = 1;

        /**
         * 從第sum_people=1個人開始找起,看其兩兩生日不等時,事件概率是否成立。
         * 如果不成立,則sum_people+1。
         */
        for (sum_people = 1;sum_people<=sum_day+1;sum_people++){
            //P{Ak}
            double Pa = ((sum_day)-sum_people+1)/sum_day;

            //P{Bk} = P{B(k-1)} * P{Ak}
            Pb = Pb*Pa;

            //如果1-P{Bk} >=50%
            if ((1-Pb)>= 0.5){
                return sum_people;
            }
        }

        return sum_people;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM