標籤:過程 組織 條件 重複 輸入 計算 == 約瑟夫問題 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)).
所以就是這樣了!!!
C++ 新約瑟夫問題