poj 3517 约瑟夫环
最简单的约瑟夫环,虽然感觉永远不会考约瑟夫环,但数学正好刷到这部分,跳过去的话很难过
直接粘别人分析了
约瑟夫问题:
用数学方法解的时候需要注意应当从0开始编号,因为取余会等到0解。
实质是一个递推,n个人中最终存活下来的序号与n-1个人中存活的人的序号有一个递推关系式。
分析:
假设除去第k个人。
0, 1, 2, 3, ..., k-2, k-1, k, ..., n-1 //original sequence (1)
0, 1, 2, 3, ..., k-2, , k, ..., n-1 //get rid of kth person (2)
k, k+1, ..., n-1, 0, 1, ..., k-2 //rearrange the sequence (3)
0, 1, ..., n-k-1, n-k, n-k+1, ..., n-2 //the n-1 person (4)
我们假设f(n)的值为n个人中最后存活的人的序号,则
注意到(2)式(3)式(4)式其实是同一个序列。//这个很重要啊,要想清楚,这三个是同一个式子
注意(1)式和(4)式,是同一个问题,不同的仅仅是人数。
假设我们已知f(n-1),即(4)式中最后剩下的人的序号,则(3)式所对应的序号,就是f(n),即(1)式n个人中最后存活的序号。
而从(3)(4)式中我们不难发现有这样一个递推式:
f(n) = (f(n-1) + k) % n
显然,f(1) = 0。
于是递推得f(n)
因为是从m开始,所以递推的最后要单独列出来
普通的约瑟夫是从0开始
1 #include <stdio.h> 2 3 int main() 4 { 5 int n, k, m, i, x; 6 while (scanf("%d%d%d", &n, &k, &m) != EOF) { 7 if (n==0 && k==0 && m==0) break; 8 x = 0; 9 for (i=2; i!=n; ++i) 10 x = (x + k) % i; 11 x = (x + m) % i + 1; 12 printf("%d\n", x); 13 } 14 return 0; 15 }