1. 程式人生 > >北大ACM(1012Joseph)程式碼

北大ACM(1012Joseph)程式碼

/*
	Memory 92K Time 47MS
*/
#include <stdio.h>
#include <stdlib.h>


/*
	解約瑟夫問題
	假如存在n個人 其中有k個壞人k個好人 每隔m個月就殺掉一個人,你需要保證所有的壞人都在好人前面被殺掉
	並且最後剩下一個好人
	現在要求你輸入 k  其中前一個k的數量表示好人的數量 後一個k表示壞人的數量
	然後輸出與k對應的最小m
*/
/*
	計算出 約瑟夫問題的公式為 
	(m + start -1) % (n - killCount)			
	(輪數m + 開始下標start - 1) % (數字總數n - 以及被kill的數字數量killCount)			
	獲取下一輪被kill的數字下標,其中下標不為實際上的下標 而是跳過被kill的number 的下標
	也就是當前剩餘數的下標
*/
#define MAX_SIZE 14 int calc(int m, int n); int main() { int gResult[MAX_SIZE]; //儲存題目要求的1-13個數字對應的結果 int m, k; for (k = 1; k < MAX_SIZE; ++k) { m = k + 1; //對於給定一個數字 它的週期數不會少於自身+1 while (1) { if (calc(m, k * 2)) { gResult[k - 1] = m; break; } else if (calc
(m + 1, k * 2)) { gResult[k - 1] = m + 1; break; } m += k + 1; //每次將輪數m遞增 增長率至少為 k } } while (scanf_s("%d", &k) && k) { printf_s("%d\n", gResult[k - 1]); } return 0; } int calc(int m, int n) //對於給定的m輪數來計算出是否能夠滿足數字總數n的要求 { int killCount = 0; int start = 0; //每次開始的下標
///迴圈進行檢測 如果出現了下標小於 n / 2表示該m為不可行方案 直接返回假 while (n - killCount > n / 2) { start = (m + start - 1) % (n - killCount); if (start < n / 2) return 0; killCount++; } return 1; }