1. 程式人生 > >對於約瑟夫環的數學解法的理解

對於約瑟夫環的數學解法的理解

寒假的時候看到了約瑟夫環的數學解法,感覺很厲害,不過一直沒有機會再進一步的看一看它的證明,今天下午有時間了,我就闡述一下我的理解

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

約瑟夫環問題模擬是可以做的,但是執行時間太恐怖了,它的遞推數學解法簡單得喪心病狂,其實想來這種規律性極強的問題應該都是有遞推解法的

設 一共有n人,編號1~n,每報到第m人時出列(事實上等同於編號0~n,報到第m-1個人出列),此時第k個人出列

最開始:1  2  3  4  .....n;

出列後:1  2  3  4 ....  k-1  k+1  k+2...n;

將m+1號以後的資料調到1之前,然後將m+1號設定為1;

             調整後

k+1

k+2

k+3

k+4

......

n

1

2

3

......

k-1

         設定後

1

2

3

4

.....

n-k

n-k+1

n-k+2

n-k+3

......

n-1

可見一次出列前後序號的函式關係:設調整序號後的序號為X,調整前的序號為y,則有 X = y + k, 此時 k = m % n; 代入得     X  =  (y + m % n)% n ;  // X 大於 n 時取餘; 化簡得     X  =  (y + m )% n ; 每一次出列前後的變化都如此,n人中出列 n-1 人,即調整過程迴圈 n-1 次,最後一個剩下的成員序號一定為 1,可逆推求得最開始的序號 化為遞迴式為  F[ n ]  =  (F[ n - 1 ] + m)% n; 之後的程式實現就很簡單了。無論是遞推還是直接計算,時間複雜度都是O(n) ++++++++++++++++++++++++++++++++++++++++++++ 看了一下別人的部落格,發現這其中還存在一個問題,當我們把 F[1] 設定為 1 時(即最後剩下的元素是1,相當於整個序列由1開始排到 n), 當 (y + m )% n =  0(如 n = 2, k = 3) 時會存在空值,因為序列中並沒有0號元素,解決這個問題有兩種方法:
  1. 設定判斷條件:
    if( F[n] == 0){
        F[n] = n;
    }
    因為當求得的值是0時意味著 X 被 n 整除,即 X = n;
  2. 將序列第一個元素序號改為0,即
    F[1] = 0;
    此時數列中的序號是 0 ~ n-1,而遞推式所求值的範圍也是 0 ~ n-1,正好可以相互對應