问题描述
n个人排成一圈,编号0~n-1,确定一个数字m,从第一个人开始报数,数到m的那个人出圈,然后重新从出圈的下一个人开始报数,直到m再次出圈,最后剩一个人时,他的号码是多少?
-
公式
f(1) = 0;
f(n) = (f(n-1) + m)%n; -
推导
0 1 2 3 … k-1 k k+1 k+2 … n-2 n-1
假设 k-1 出队列,出队列后
0 1 2 3 … k k+1 … n-2 n-1
由于是一个环,所以把k前面的数据放到n-1 后面
0 1 2 3 … k k+1 … n-2 n-1 n n+1 … n+k-2
最后一个数是 n-1+(k-1)
省去前面的数据
k k+1 … n-2 n-1 n n+1 … n+k-2
每个数都-k
0 1 2 … n-1 n-2
因此可推出 n序列 到 n-1序列的关系。
如果已知n-1序列的最后一个号码数,则可反推n序列的最后一个号码数,假设n-1 中是 x,则反推
- x+k
- (x+k)%n 此时下标位置位于n-1之后,所以求余n,使其回到0 到 n-1中
- f(n)代表,序列长度为n时最后一个号码数
- 则f(n-1)代表,序列长度为n-1时的最后一个号码数
- 故f(n) = (f(n-1)+k)%n
#include<iostream>
using namespace std;
int main() {
int amountOfPeople, count;
cout << "Please input amount of people :";
cin >> amountOfPeople;
cout << "please input count :";
cin >> count;
int start = 0;
int result = 0;
int livePeople = amountOfPeople;
for (int index=1; index < amountOfPeople; index++) {
result = (result+count)%(index+1);
}
cout << result << endl;
}