牛客网: 约瑟夫环 ->题目地址
n个人(0,1,2,3,4…n-1),围成一圈,从编号为k的人开始报数,报数报到m的人出队(报数是1,2,…m这样报的)。下次从出队的人之后开始重新报数,循环往复,当队伍中只剩最后一个人的时候,那个人就是大王。现在,给定n,k,m,
请你求出大王的编号。
输入描述:
输入一行包含三个整数n,k,m
1<=n<=100,1<=k<=n-1,1<=m<=100
输出描述:
输出一个整数
示例1
输入
5 1 2
输出
3
感谢大佬的博客(以下是链接地址)
约瑟夫环问题的两种解法(详解)
照着大佬的思路终于把题目写了出来,然后按自己的理解写了一下题解,思路都一样的,最后加了一些第k个位置的取余
,就ac了
假设有10个人,从第五个人开始报数,报到3的出队
因为是从第五个人开始报数,位置不好处理
原来的标号:
0 1 2 3 4 5 6 7 8 9
每次移动下标都会 -3
我们更改一下下标,把5的下标变成0,这样就可以从0开始统计了
初始队伍:
5 6 7 8 9 0 1 2 3 4
出队一人
第一步我们要从0开始删除第三个人:2%10=2 我们让下标为2个人出队,于是我们的标号就变成了
5 6 7 8 9 0 1 3 4 初始队伍的((0+2)%10=2)
我们把3号标记为新的起点0,更新下标后
2 3 4 5 6 7 8 0 1
出队二人
同理我们从0号开始数,第三个人出队,2%9=2,于是:
3 4 5 6 7 8 0 1 第一支队伍的2%10=2 即初始队伍的(2+3)%10=5
跟新下标后,
0 1 2 3 4 5 6 7
出队三人:
第三个人出队,2%8=2,下标为2的人出队,于是:
0 1 3 4 5 6 7 第二支队伍的2%8=2 即第一支队伍的(2+3)%9=5 初始队伍的(5+3)%10=8
更新下标后,
5 6 0 1 2 3 4
出队4人。。。出队9人,最后剩下一个人的时候,队伍是:
出队九人:
0
可以得到,无论队伍是什么样子的,最后剩下一个人的时候,下标一定会是0,而每次移动下标都会-3
f(9)=0;
第9支队伍的0号,即第8支队伍的 f(8)=(f(9)+3)%2=1;
第8支队伍的1号,即第7支队伍的 f(7)=(f(8)+3)%3=1;
。。。
倒推一下就是
f(1)=0;
f(2)=(f(1)+3)%2=1;
f(3)=(f(2)+3)%3=1;
。。。
f(n)=f(n-1)+3)%n
f(i)=(f[i-1]+m)%i;(i>1)
最后因为是从第k个人开始计算的,第一步操作我们把K的下标变成了0,现在还原回去(f(n)+k)%n
#include<iostream>
using namespace std;
int n,m,k;
int fun()
{
int wei=0;
for(int i=2;i<=n;++i)
{
wei=(wei+m)%i;
}
return (wei+k)%n;
}
int main()
{
cin>>n>>k>>m;
cout<<fun();
}