约瑟夫环问题

约瑟夫问题

约瑟夫问题是个著名的问题:N个人围成一圈,第一个人从1开始报数,报M的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。
例如只有三个人,把他们叫做A、B、C,他们围成一圈,从A开始报数,假设报2的人被杀掉。

首先A开始报数,他报1。侥幸逃过一劫。
然后轮到B报数,他报2。非常惨,他被杀了
C接着从1开始报数
接着轮到A报数,他报2。也被杀死了。
最终胜利者是C

普通解法
#include <bits/stdc++.h>
using namespace std;


int a[100]={0};//0表示没有出局,1表示已出局
int main() {
    int n,m;//n个人,报到m号的人出局
    int cnt=0,k=0;//cnt表示目前出局的人数,k记录当前报到了多少号
    int i=0;//i相当于一个指针,遍历整个数组,然后又从头开始遍历有人出局后的数组;
    cin>>n>>m;
    while(cnt!=n){
        i++;
        if(i>n) i=1;
        if(a[i]==0){//当他未出局时
            k++;
            if(k==m){//当报到了m号时
                a[i]=1;//让这个人出局,并将他标记为1
                cnt++;//出局人数加一
                cout<<i<<" ";//注:当人员是从0开始编号时,应该输出 i-1(!!!!!!)
                k=0;//清空k,从1开始报数
            }
        }
    }

    return 0;
}
/*
人员从1开始编号:1 2 3 4 5 6 7 8 9 10
10 3
3 6 9 2 7 1 8 5 10 4 
*/

/*
人员从0开始编号: 0 1 2 3 4 5 6 7 8 9
10 3
2 5 8 1 6 0 7 4 9 3 
*/
公式法

f (N,M) = ( f (N−1,M) + M ) %N

f(N,M)表示,N个人报数,每报到M时杀掉那个人,最终胜利者的编号
f ( N − 1 , M ) f(N-1,M)f(N−1,M)表示,N-1个人报数,每报到M时杀掉那个人,最终胜利者的编号

//这里的公式法:人员从0开始编号
#include<bits/stdc++.h>
using namespace std; 
int n,m;
int main(){
	cin>>n>>m;
	int success=0;
	for(int i=2;i<=n;i++){
		success=(success+m)%i;
	}
	cout<<success;//这里输出的是当人员从0开始编号时的成功的那个人,
	//如果人员从1开始编号,那么最后成功的那个人是:success+1.
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序媛小y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值