Josephus Problem (約瑟夫環數學解法)

來源:互聯網
上載者:User
       約瑟夫環是一個非常經典的數學問題,n個人圍成一圈,從1開始報數,每當有人報到m時,他被淘汰,下一個人繼續從1開始報數,問最後的獲勝者是誰。        有一種很經典的演算法是用鏈表/數組來類比整個遊戲的過程,但是當n , m 都很大的時候這個方法就顯然行不通了。有沒有更便捷的方式來解決這個問題呢。       我們可以從數學的角度來分析一下這個問題。首先我們通過思考可以得到一個很顯然的結論,n個人時的獲勝者和這n個人淘汰掉一個人繼續遊戲下的獲勝者一定是同一個人。(有點像廢話...)所以如果我們能確定 n-1個人時候的獲勝者也就可以得到 n 個人時候的情況,因為兩者的排列存在一種對應關係。 考慮n = 6 m = 3的情況        0 1 2 3 4 5        3 4 5 0 1 2 可以很明顯的看出上下兩行存在著 + m 模 n的對應關係。        這樣這個問題就可以通過遞推的方式解決了, f[i] 為 場上有 i 個人時,最後獲勝者的編號(從零開始)。        那麼就存在著這樣的遞推式   f[i] = ( f[i-1] + k ) % i   我們還可以知道 f[1] = 0 所以可以通過這個遞推式輕鬆的得到答案啦~
代碼實現:(HDU 2925)
/*    @Author: wchhlbt    @Date:   2017/3/9*/#include <bits/stdc++.h>#define Fori(x) for(int i=0;i<x;i++)#define Forj(x) for(int j=0;j<x;j++)#define maxn 1005#define inf 0x3f3f3f3f#define ONES(x) __builtin_popcount(x)using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> P;const double eps =1e-8;const int mod = 10007;const double PI = acos(-1.0);int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};int main(){    int n,d;    while(cin>>n>>d && n+d){        int ans = 0;        for(int i = 2; i<=n; i++)            ans = (ans+d)%i;        cout << n << " " << d << " " << ans+1 << endl;    }    return 0;}
這個問題還可以進一步最佳化,當n非常大,k卻很小的時候,我們甚至沒有必要遍曆所有的 i ,考慮這個式子ans = (ans+d)%i , 當 i已經很大了的時候可能 ans + k*d < i , 這種情況下我們完全沒有必要一步一步的去類比,因為這個數值始終沒有變化,所以可以一次性跳躍若干的值達到最佳化演算法的目的。
AC代碼:(HDU 3089)
/*    @Author: wchhlbt    @Date:   2017/3/14*/#include <bits/stdc++.h>#define Fori(x) for(int i=0;i<x;i++)#define Forj(x) for(int j=0;j<x;j++)#define maxn 1005#define inf 0x3f3f3f3f#define ONES(x) __builtin_popcount(x)using namespace std;typedef long long ll;typedef long double ld;typedef pair<int,int> P;const double eps =1e-8;const int mod = 10007;const double PI = acos(-1.0);int dx[4] = {0,0,1,-1};int dy[4] = {1,-1,0,0};int main(){    ll n,k;    while(scanf("%I64d%I64d",&n,&k)!=EOF){        if(k==1){            printf("%I64d\n",n);            continue;        }        ll ans = 0;        for(ll i = 2; i<=n; ){            if(ans+k<i){                ll num;                if((i-1-ans)%(k-1)==0)                    num = (i-1-ans)/(k-1) - 1;                else                    num = (i-1-ans)/(k-1);                if(i+num>n){                    ans = (ans + (n+1-i)*k)%n;//因為目前ans儲存的是只有i-1個人時的倖存編號                    break;                }                i += num;                ans = (ans + num*k)%i;            }            else{                ans = (ans+k)%i;                i++;            }        }        printf("%I64d\n",ans+1);    }    return 0;}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.