约瑟夫环:n 个人(编号 0~(n-1)),从 0 开始报数,报到(m-1)的退出,剩下的人继续从 0 开始报数。求胜利者的编号。
为取模方便,假设下标从 0 开始,倒推分析:
假设该轮有 n 个人,那么上一轮(n+1)人,编号为 0 的人上一轮编号为 k,也即编号为 f[n]的人上一轮编号为(f[n]+k)%(n+1)。
我们知道最后剩下的人在最后一轮编号肯定为 0,那么这样不断倒推就可以推出其在第一轮的编号,也即他本来的编号。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
using namespace std;
int f[1000005];
int main(){
//freopen("a.txt", "r", stdin);
int n, m;
while(~scanf("%d%d", &n, &m) && n && m){
f[1] = 0;
for(int i = 2; i <=n; i++){
f[i] = (f[i-1]+m)%i;
}
cout << n << " " << m << " " << f[n]+1 << endl;
}
return 0;
}