C++ 新約瑟夫問題


#include<iostream>
#include<cmath>
using namespace std;
int main()
{
    int n,sum=0,j,i,k,lpl,a[100000],b[100000];
    cin>>n;
    a[1]=1,b[1]=1;        
    for(int i=2;i<=n;i++)
    {
            a[i]=(a[i-1]+1)%i+1;
    if(a[i]==i)b[i]=i;
    else b[i]=b[a[i]];
    }
    cout<<b[n]+n; 
}

又是一道遞推  代碼如上;

試題描述:

你一定聽說過經典“約瑟夫”問題吧?現在來組織一個皆大歡喜的新游戲:假設 n 個人站成一圈,從第 1 人開始交替的去掉游戲者,但只是暫時去掉(例如,首先去掉 2),直到最后剩下唯一的幸存者為止。幸存者選出后,所有比幸存者號碼高的人每人將得到 1 塊錢,並且永久性地離開,其余剩下的人將重復以上過程,比幸存者號碼高的人每人將得到 1 塊錢后離開。一旦經過這樣的過程后,人數不再減少,最后剩下的那些人將得到 2 塊錢。請計算一下組織者一共要付出多少錢?

例如,第一輪有 5 人,幸存者是 3,所以 4、5 得到 1 塊錢后離開,下一輪幸存者仍然是 3,因此沒有人離開,所以每人得到 2 塊錢,總共要付出 2+2*3=8 塊錢。

輸入:

一行一個整數 n。

輸出:

一行一個整數,不超過65535,表示總共要付出多少錢。

輸入實例:

10

輸出實例:

13

 

首先,每個人都會得到1塊錢,只有最后的那些幸存者多得到了1塊錢。所以只要求出最后會幸存的人即可。

假設經過m次出圈操作后還剩final(m)個人,此時的人數已經不可以再減少了,則問題的解應該為final(m)+n.可是如何求final(m)呢?

當第i次的final(i)=i時,人數就不會再減少了,此時的i即為m,否則,就需要對剩下的final(i)個人再進行報數出圈操作;

會有兩種情況:1 設jose(i)為幸存者的編號,設報道K的人出去,則jose(i-1)可以理解為第一輪第一次報數,k出去后的狀態,k出去后會從k+1繼續報數,此時圈中有i-1個人,從k+1開始報數,編號jose(i)為:k+1,K+2......i,1,2.....,k-1;

                          2 可以人為地把這個圈逆時針轉k個單位,此時報數的編號jose(i-1):1,2.....,i-k,i-k+1,i-k+2....,i-1;

從上面兩種情況可以發現除了i和i-k以外,其他所有數據都滿足規律:jose(i)=(jose(i-1)+k)mod i。對這個式子稍微調整一下,變成的公式都滿足了:jose(i)=(jose(i-1)+1)mod i+1;

至此這個問題的遞推公式就出來了,邊界條件為jose(1)=1.然后,順推求出每個jose(i),直到某一次jose(i)=i,則final(i)=i,否則final(i)=final(jose(i)).

所以就是這樣了!!!


免責聲明!

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



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