约瑟夫问题:
用数学方法解的时候需要注意应当从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)
代码如下:
View Code
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 }