约瑟夫环

牛客网: 约瑟夫环 ->题目地址
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();
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值