一开始有
n
n
n个人围成一个圈, 从
1
1
1 开始顺时针报数, 报出
m
m
m 的人被机关处决. 然后下一
个人再从
1
1
1 开始报数, 直到只剩下一个人。
我们有一个
O
(
n
)
O(n)
O(n)的递推方法:
设还有
i
i
i个人的时候幸存者是第一个人右边第
f
i
f_i
fi个人。
f
i
=
(
f
i
−
1
+
m
+
1
)
m
o
d
i
f_i = (f_{i-1} + m + 1) \mod i
fi=(fi−1+m+1)modi
如果
n
>
m
n>m
n>m,那么我们可以用另一个方法:
一次安排好前
n
m
\frac nm
mn次被处决的人的位置并求出幸存者的新位置。
A C C o d e \rm{AC\ Code} AC Code
#include<bits/stdc++.h>
#define maxn 100005
using namespace std;
int n,m,f,a,b;
int main(){
int T;
for(scanf("%d",&T);T--;){
scanf("%d%d",&n,&m);
if(m==1){
printf("%d\n",n);
continue;
}
a = 1;
for(f=0;a<=m && a<n;) a++,f = (f+m) % a;
for(;a<n;){
int t = a/(m-1);
if(t > n-a) break;
int p = a % (m-1);
f = (f-p + (f-p) / (m-1) + a+t) % (a+t) , a+=t;
}
int t = n - a , p = a - t * (m-1);
if(f >= p) f = (f - p + (f - p) / (m-1) + a + t) % (a + t) , a += t;
else f = (f-p+a+t) % (a+t);
printf("%d\n",f+1);
}
}