先展示用数学的通项公式递推求解 (fun(n-1,m)+m)%n
int fun(int n,int m)
{
if(n==1)
return 0;
else
return (fun(n-1,m)+m)%n;
}
int main(){
int n,m,k;
scanf("%d%d%d",&n,&k,&m);
printf("%d",(fun(n,m)+k)%n);
}
这样子看起来简单但是很难理解,推导起来很复杂,但是可以记一下。 接下来展示用数组这种易于理解的解法 对于求解这道题可以定义一个数组用来存放约瑟夫环内的各元素,并且这里要将数组内个元素初始化为0。
int mon[102] = { 0 };
初始化为0要放在main函数里进行,不要作为一个全局变量,不然只有90%的通过率。 对数组内的下标0~n-1的进行赋值1、2、3...n
for (int i = 0; i < n; i++) {
mon[i] = i + 1;
}
设置pos作为下标在给mon[i]赋值时是从0下标开始的,那么对pos的初始值是要赋值为k-1才是前面for循环中所对应的下标,对num直接赋值为n
pos = k - 1, num = n;
接下来时核心代码区 当num>1时即还没有剩下一个人,进入while循环。在这里先分一个if-else语句若当前的这个值为0那么下标pos往后挪一位。因为这是一个环状,当下标为最后一位时候的下一位是第一位,我们的挪位采用
pos = (pos + 1) % n;
或者把上一个代码块更换为下面的代码块
pos++;
if(pos>=n)pos=0;
若mon[pos]值大于0(不等于0)进入下一个if-else语句 当计数器count不等于m时计数器count加一,下标往后移,、。等于0时令当前下标的值为0标志这个值被删除,下一次直接跳过,计数器count重置为1,总个数-1,坐标往后移。 输出时只要找不为0的下标是几就好了。
下面是全部的代码
#include<bits/stdc++.h>
using namespace std;
int n, m, k;
int main() {
cin >> n >> k >> m;
int num, count = 1, pos;
int mon[102] = { 0 };
if (n == 0 || m == 0) {
return 0;
}
for (int i = 0; i < n; i++) {
mon[i] = i + 1;
}
pos = k - 1, num = n;
while (num > 1)
{
if (mon[pos] > 0) {
if (count != m) {
count++;
pos = (pos + 1) % n;
}
else {
mon[pos] = 0;
count = 1;
num--;
pos = (pos + 1) % n;
}
}
else {
pos = (pos + 1) % n;
}
}
for (int i = 0; i < n; i++) {
if (mon[i] > 0) {
cout << mon[i] << endl;
}
}
return 0;
}