2014-11-25 10:54:00
思路:经典的约瑟夫环问题,思考一下递推过程:假设一圈人的编号:0,1,2,3,...,n-1,总共n个人,报数为m
令f(n)为第n轮出列人的位置,可知当前轮选的人和上一轮结束的位置有关,所以f(n)和f(n-1)有关,且关系为:
f(i) = (f(i-1)+m)%(n-i+1)。【如f(2)=(f(1)+m)%(n-1)】
由于这题k很小,所以直接枚举m,并且要记录每个k的答案防止重复计算。
1 /************************************************************************* 2 > File Name: p1012.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 25 Nov 2014 10:24:45 AM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 27 int k,n; 28 int f[20]; 29 int ans[20]; 30 31 int main(){ 32 while(scanf("%d",&k) != EOF && k){ 33 if(ans[k]){ 34 printf("%d\n",ans[k]); 35 continue; 36 } 37 n = 2 * k; 38 f[0] = 0; 39 for(int m = k; ; ++m){ 40 int flag = 1; 41 for(int i = 1; i <= k; ++i){ 42 f[i] = (f[i - 1] + m) % (n - i + 1); 43 if(f[i] < k){ 44 flag = 0; 45 break; 46 } 47 } 48 if(flag){ 49 printf("%d\n",m + 1); 50 ans[k] = m + 1; 51 break; 52 } 53 } 54 } 55 return 0; 56 }