這裡在推一遍公式
由於每次都是由1開始,所以可以把1排除掉,直接將城市數變成k-1,把2當作1.
//k+1 1
//…… ……
//n n-k
//n+1 (就是原來的1) n-k+1
//…… ……
//k+n-2 n-1
//本輪x 下一輪x『
但是本輪只剩下n-1個數了,而編號還是從1~n(中間缺少了ans[i-1]),中斷了,而下一輪是連續的
所以重新排序成1~n-1,否則從下一輪轉換回本輪數字對不上
下一輪轉本輪 x = x』+k = x'+ans[i-1]
再重新得出順序 a = (x-2)%(n-1)+1 這樣原來本輪的編號就由1、2、……ans[i-1]-1、ans[i-1]+1、……n 變成1~n-1
合起來a = (x'+ans[i-1]-2)%(n-1)+1。
如果知道下一輪選中的數在下一輪中的位置x',那麼就可以知道該數在本輪的位置a
x』 = (m-1)%(n-1)+1
而這個a就是ans[i],如果ans[i]==1,就是選中的城市ulm,m不符合
#include#include#include#include#include#include#include#include#include#includeusing namespace std;
#define lch(i) ((i)<<1)
#define rch(i) ((i)<<1|1)
#define sqr(i) ((i)*(i))
#define pii pair#define mp make_pair
#define for(i,b,e) for(int i=b;i<=e;i++)
#define fore(i,b,e) for(int i=b;i>=e;i--)
#define ms(a) memset(a,0,sizeof(a))
const int maxnum =21252;
const int mod = 10007;
int n;
////#define _debug_
int main()
; //打表,儲存各個k值對應的m值
int k;
while(fin>>k)
{ if(!k)
break;
if(joseph[k])
{ cout<
pku2244約瑟夫環問題
題意 n個城市 標號1,2,n 輪流斷網,先停1號城市,然後每m個城市斷網,斷了的就不用計入在內了。分析 約瑟夫環殺人遊戲的乙個變種。自己總算能用之前的公式套了。我們已知的結論是 f i 表示i個人玩遊戲報m退出最後勝利者的編號,最後的結果自然是f n 遞推公式 f 1 0 f i f i 1 m ...
poj 3517 約瑟夫環。。。。。
無論是用鍊錶實現還是用陣列實現都有乙個共同點 要模擬整個遊戲過程,不僅程式寫起來比較煩,而且時間複雜度高達o nm 當n,m非常大 例如上百萬,上千萬 的時候,幾乎是沒有辦法在短時間內出結果的。我們注意到原問題僅僅是要求出最後的勝利者的序號,而不是要讀者模擬整個過程。因此如果要追求效率,就要打破常規...
POJ 1012 約瑟夫環
poj的約瑟夫環問題是原本約瑟夫環的一種變形。約瑟夫環 有n個人,從第乙個人開始報數,數到第m個人就退出,依次迴圈,最後剩下的人為勝利者。可以用迴圈鍊錶和陣列的方法做,當m,n比較小時可以一試 迴圈鍊錶,數到就刪除,數到只剩乙個就輸出 陣列,第0個位置數值置為n,其他照常 a 1 1,a 2 2.數...