poj 1012 Joseph(約瑟夫環求每次出圈人的序號)
阿新 • • 發佈:2019-02-11
有k個好人和k個壞人,前k個是好人後k個是壞人。模擬約瑟夫環,每次數到m的數要被殺死,然後他後面的人從1開始報數。重複這個過程。要求輸出最小的m,使得前k個被殺死的人都是壞人。
因為k比較小,我們可以列舉m,列舉到某個m滿足前k個出圈人的序號都大於等於k,那麼m就是所求。
以k=3為例,6個人的編號為0 1 2 3 4 5 ,好人的序號為0~k-1,壞人的序號是 k~2*k-1。
首先推出每次出圈的人在當前序列中的序號,用ans[i]表示第i個出圈的人的序號。
若m = 5,
那麼ans[1] = 4,ans[2] = 3,根據這兩個數我們可以推出ans[i] = (ans[i-1] + m-1)%(n-i+1),其中ans[0] = 0。注意這裡的ans[i]是在前一輪殺死一個人後重新編號。
#include <stdio.h> #include <iostream> #include <map> #include <set> #include <list> #include <stack> #include <vector> #include <math.h> #include <string.h> #include <queue> #include <string> #include <stdlib.h> #include <algorithm> #define LL long long #define _LL __int64 #define eps 1e-12 #define PI acos(-1.0) #define C 240 #define S 20 using namespace std; int f[30]; int ans[30]; int main() { int k; memset(ans,-1,sizeof(ans)); while(~scanf("%d",&k)) { if(k == 0) break; if(ans[k] != -1) //如果已經計算過,儲存下來不再重複計算 { printf("%d\n",ans[k]); continue; } int n = k*2; //總人數 int m = 1; //從1列舉 f[0] = 0; for(int i = 1; i <= k; i++) //在m下求出前k個出圈的人的編號 { f[i] = (f[i-1]+m-1)%(n-i+1); if(f[i] < k) //好人被殺死,m不符,好人的編號一直是0~k-1 { i = 0; m++; } } ans[k] = m; printf("%d\n",ans[k]); } return 0; }