首页 > 试题广场 >

约瑟夫环

[编程题]约瑟夫环
  • 热度指数:14135 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
\hspace{15pt}n 个人(编号 0\sim n-1)围成一圈,从编号为 k 的人开始报数,报数依次为 1,2,\dots,m,报到 m 的人出队。下次从出队者的下一个人开始重新报数,循环往复,直到队伍中只剩最后一个人,该人即"大王"。

\hspace{15pt}给定三个正整数 n,k,m,请输出最后剩下的"大王"编号。

输入描述:
\hspace{15pt}在一行中输入三个整数 n\left(2 \leqq n \leqq 100 \right),k\left(0 \leqq k \leqq n-1\right),m\left(1 \leqq m \leqq 100\right),用空格隔开。


输出描述:
\hspace{15pt}输出一个整数,表示最后剩下的"大王"编号。
示例1

输入

5 1 2

输出

3

说明

初始队列编号为 [0,1,2,3,4],从编号 1 开始报数:

\hspace{8pt}1(1),2(2)\to 2 出队,剩余 [0,1,3,4]

\hspace{8pt}3(1),4(2)\to 4 出队,剩余 [0,1,3]

\hspace{8pt}0(1),1(2)\to 1 出队,剩余 [0,3]

\hspace{8pt}3(1),0(2)\to 0 出队,剩余 [3],输出 3
    int n, k, m;
    cin >> n >> k >> m;

    vector<int> a(n);
    for (int i = 0; i < n; ++i)
        a[i] = i;

    while (a.size() > 1) {
        k = (k + m - 1) % a.size();
        a.erase(a.begin() + k);
    }
    cout << a[0] << endl;
发表于 2025-11-05 15:05:44 回复(1)
#include <iostream>
using namespace std;
 
int main() {
    int n,k,m; // 人数,开始位置,报数步长
    cin>>n>>k>>m;  
    int a[n];  // 标记是否出列
    int count=n;
    int cnt,num=k;  // num = k,用于标记当前报数人的位置
    for(int i=0;i<n;i++){
        a[i]=i;         // 初始化数组,每个人都有自己的编号
    }
    cnt=0;          // 计数器,当前报数的步数
    while (count>=1) {       // 还有未出列的人就循环
        if(a[num]!=-1) {     // 若当前报数人未出列
            cnt++;           // 则报数计数器+1,表示有人报数
            if(cnt==m) {     // 若数到了m!
               a[num]=-1;    // 当前人出列
               count--;      // 剩余人数--
               cnt=0;        // 报数计数归零!
            }
        } 
        if(num==n) num=1;    //假设转了一圈,则从头开始再来
        else num++;          // 
    }
    cout<<num-1<<endl;
}

发表于 2025-07-16 09:47:58 回复(0)
n, k, m = map(int, input().split())
L = [i for i in range(0,n)]
for _ in range(1, n):
    k = (k+m-1)%n
    n = n-1
    L.remove(L[k])

print(L[0])

发表于 2025-06-18 00:43:21 回复(1)
#include <iostream>
using namespace std;
#include <list>
#include <iterator>

int main() {
    int n,k,m;
    cin >> n >> k >> m;
    list<int> lst;
    int count = 0;
    for(int i = 0; i < n; ++i)
    {
        lst.push_back(i);
    }

    list<int>::iterator curr = lst.begin();
    advance(curr, k);   

    while(lst.size() > 1)
    {
        ++count;
        if(count == m) 
        {
            curr = lst.erase(curr);
            if(curr == lst.end()) {curr = lst.begin();}
            count = 0;
        }
        else 
        {
            ++curr;
            if(curr == lst.end()) {curr = lst.begin();}
        }
    }
    cout << *lst.begin() << endl;
}

发表于 2025-12-14 00:19:07 回复(0)
n,k,m=map(int,input().split())
l=list(range(n))
while n>=2:
    k=(k+m-1)%n
    l.pop(k)
    n-=1
print(*l)

发表于 2025-11-04 14:52:11 回复(0)
#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 读取输入:总人数n,起始位置k,报数步长m
    int n, k, m;
    cin >> n >> k >> m;
   
    // 创建向量保存所有人员(编号0到n-1)
    vector<int> array;
    for(int i = 0; i < n; i++){
        array.push_back(i);
    }
   
    // 设置当前起始位置(确保在[0, n-1]范围内)
    int current = k % n;
   
    // 当还有超过1人时继续淘汰
    while(array.size() > 1){
        // 计算下一个要淘汰的人的位置:
        // 1. 从当前位置前进m-1步(因为报数从1开始)
        // 2. 使用当前剩余人数取模,实现环形结构
        current = (current + m - 1) % array.size();
       
        // 淘汰当前位置的人
        array.erase(array.begin() + current);
    }

    // 输出最后剩下的"大王"
    cout << array[0];
}
发表于 2025-08-19 15:40:12 回复(0)
#include <stdio.h>
int main() 
{
    int n, k, m;
    scanf("%d %d %d", &n, &k, &m);
    int arr[n],a=0,p=k;//arr[]s数组标记0出队,a标记出队人数,p标记当前未出队的首个报数编号
    for(int i=0;i<n;i++) arr[i] = 1;
    while(n-1-a)
    {
        for(int j=0;j<m-1;j++)
        {
            do{
              if(++p==n) p=0;
            }while(!arr[p]);//找出出队编号
        }
        arr[p]=0;
        a++;
        do{
            if(++p==n) p=0;
        }while(!arr[p]);//找出出队后下个首个报数编号
    }
    printf("%d\n",p);
    return 0;
}

发表于 2025-09-15 20:51:03 回复(0)
n,k,m=map(int,input().split())
lst=list(range(n))
start=k
while len(lst) > 1:
    for _ in range(m-1):
        start = (start + 1) % len(lst)
    removed_person = lst.pop(start)
print(lst[0])
   
发表于 2025-07-30 15:40:51 回复(0)
#include<stdio.h>
int main()
{
    int n, k, m;
    scanf("%d %d %d", &n, &k, &m);
    int a=n;
    int count = 0;
    int current = k-1;
    int arr[100] = { 0 };
    for (int i = 0; i < n; i++)
    {
        arr[i] = 1;
    }
    while (a > 1)
    {
        if (arr[current])
        {
            count++;    
            if (count == m)
            {
                arr[current] = 0;
                count = 0;
                a--;
            }
                   
        }
            current = (current + 1) % n;
    }
    for (int i = 0; i < n; i++)
    {
        if (arr[i])
        {
            printf("%d", i+1);
            break;
        }
    }
    return 0;
}
发表于 2025-12-07 14:12:10 回复(0)
#include <stdio.h>
int main() {
    int n = 0, k = 0, m = 0, count = 0, step = 0, current;
    int people[1000];
    //count是移除的人
    //step是报的数
    //current是现在的位置
    scanf("%d %d %d", &n, &k, &m);
    current = (k - 1 + n) % n;
    for (int i = 0; i < n; i++) {
        people[i] = 1;
    }//定义一个全是1的,个数为n的数组,1是还在队伍里面,0是已经出了队伍
    while (count < n -
            1) { //让移除的人还没到n的时候循环,一直持续到只有一个人在队伍里面
        //开始报数
        while (step < m) { //另起一个报数的计数器step
            if (people[current] == 1)
                step++;//如果这个人报数还没有到m,那么直接跳过他,报数计数器+1
            if (step < m)
                current = (current + 1) % n;
        }
        //一轮报数结束,开始换下一组
        //清除计数器,把移除的人标记成0
        step = 0;
        people[current] = 0;
        count++;
        //开始下一个

        while (people[current] == 0)
            current = (current + 1) %
                      n;//取模就相当于让最后一个直接跳到第一个,且不用担心溢出问题

    }
    for (int i = 0; i < n; i++) {
        if (people[i] == 1)
            printf("%d", i + 1);

    }

    return 0;
}

发表于 2025-12-01 22:27:09 回复(0)
#include <iostream>
using namespace std;

int main() {
int a, b,c;
cin >>a >>b>>c;
int nowPoint =b;
int count=0;
int num =a;
int res[101]={0};
while(1){
if(res[nowPoint]==0){
//未排除
count++;
if(count%c==0){
if(num==1){
cout<<nowPoint;
break;
}
res[nowPoint]=1;
num--;
}
}
nowPoint++;
nowPoint%=a;
}

}
// 64 位输出请用 printf("%lld")
发表于 2025-11-16 23:20:35 回复(0)
#include <stdio.h>
int main() {
    int n, k, m, arr[100];
    scanf("%d %d %d", &n, &k, &m);
    int l = n;
    for (int i = 0; i < n; i++)arr[i] = 1;
    while (n > 1) {
        int count = 0;
        while (count < m) {
            if (arr[k] == 1) {
                count++;
                if (count == m) {
                    arr[k] = 0;
                    n--;
                }
            }
            k = (k + 1) % l;
        }
    }
    for (int i = 0 ; i < l; i++) {
        if (arr[i] == 1) {
            printf("%d", i);
            break;
        }
    }
}
发表于 2025-11-14 22:03:10 回复(0)
#include <iostream>
using namespace std;
#include<vector>
int main() {
   int n,k,m;
   cin>>n>>k>>m;
   vector<int>v;
for(int i=0;i<n;i++){
    v.push_back(i);//i仅仅作为选手的编号 不要对索引i操作
}
int begin_position=k;   //position:以0开始计数
while(v.size()>1){
    int pop_position=(begin_position+m-1)%v.size();
   v.erase(v.begin()+pop_position);
   begin_position=(pop_position)%v.size();//出队后的位置 就是 下一个开始的位置
}
cout<<v[0];
}

发表于 2025-11-04 21:39:06 回复(0)
#include <stdio.h>

int main() {
    int n, k, m;
    scanf("%d %d %d", &n, &k, &m);
    //定义队列并初始化
    int arr[n];
    for(int i = 0; i < n; i++) arr[i] = i;

    //n-1次循环
    while( n > 1){
        //计算出队编号
        k = (k+m-1) % n;
        //更新序列和n
        n--;
        for(int i = k; i < n; i++) arr[i] = arr[i+1];
        //计算报数起始编号
        k %= n;
    }

    printf("%d", arr[0]);

    return 0;
}

发表于 2025-11-01 17:50:13 回复(0)
import sys

for line in sys.stdin:
    n, k, m = map(int, line.strip().split())
    lst = list(range(n))
    for _ in range(n - 1):
        k = (k+m-1)%len(lst)
        lst.pop(k)
    print(lst[0])

发表于 2025-10-29 09:59:27 回复(0)
#include<bits/stdc++.h>
using namespace std;
int main (){
    int n,k,m,count=0;
    cin>>n>>k>>m;
    int dw = k;
    int sum = n;
    int a[110]={0};
    while(sum>1)
    {
        if (a[dw]==0)
        {  
        count=count+1;
   
            if (count==m)
                {
                a[dw]=1;
                count=0;
                sum=sum-1;
                }
        }
   
        dw=dw+1;
        if(dw==n) dw=0;  

    }
    for(int i=0;i<n;++i)
        {
            if(a[i]==0)
             cout<<i<<endl;
        }
}  
 
发表于 2025-10-11 17:45:46 回复(0)
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int n=in.nextInt(), k=in.nextInt(), m=in.nextInt();
        StringBuffer sb = new StringBuffer();
        for (int i=0; i<n; i++) {
            sb.append(i);
        }
        while (sb.length()!=1) {
            k+=m;
            if (k>sb.length()) {
                k=k%m;
            }
            sb.deleteCharAt(k-1); // 从自己开始数,所以减一
        }
        System.out.println(sb);
    }
}
还是喜欢用StringBuffer
发表于 2025-10-09 10:27:04 回复(0)
import sys

n,k,m=map(int,input().split())
arr=[]
for i in range(n):
    arr.append(i)
cont=k
for i in range(n-1):
    for j in range(m-1):
        cont=(cont+1)%len(arr)
    del arr[cont]

print(arr[0])


发表于 2025-10-06 17:55:40 回复(0)
#include <stdio.h>

int main() {
    int n,k,m,a[101],b=0,c=0,now;
    scanf("%d%d%d",&n,&k,&m);
    for(int i=0;i<=n-1;i++){
        a[i]=1;
    }
    while(b<n){
        while(1){
            if(a[k]==1){
                c++;if(c==m){
                    a[k]=0;
                    b++;
                    now=k;
                    c=0;
                    break;
                }
            }k=(k+1)%n;
        }
    }printf("%d",now);
    return 0;
}

发表于 2025-10-04 15:18:04 回复(0)
n_temp,k_temp,m_temp = input().split()
n,k,m = int(n_temp),int(k_temp),int(m_temp)
ls = list(range(n))
index = k
while len(ls)>1:
    index = (index+m-1)%len(ls)
    ls.pop(index)
print(*ls)
发表于 2025-09-27 22:13:24 回复(0)