约瑟夫的新问题(详解)

将1~M这M个自然数按由小到大的顺序沿顺时针方向围成一圈。以S为起点,先沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,再沿顺时针方向数到第N个数就出圈,然后再沿逆时针方向数到第K个数再出圈,······这样按顺时针方向和逆时针方向不断出圈,直到全部数都出圈为止。
请打印先后出圈的数的序列。

样例输入

8 1 3 2

样例输出

3 1 5 2 7 4 6 8
#include<cstdio>
int m,s,n,k,b,q,c;
int cnt,flag;
int t1,t2;
int a[5000];
int main()
{
	scanf("%d %d %d %d",&m,&s,&n,&k);
	int cnt=s-1;//这里运用了模拟地方法,所以cnt要初始化在s前
	for(int i=1;i<=m;i++)
	{
		t1=n;//方向上要几个人淘汰
		t2=k;
		if(i%2!=0)
		{//判断方向,奇顺偶逆
			while(t1>0)
			{
				if(cnt==m)
			    {
			    	cnt=0;//更新
				}
				
				if(a[++cnt]==0)
				{
					t1--;//模拟先++;
				}
		   }
		   a[cnt]=1;//数组的值位1表示出圈
		   printf("%d ",cnt);
		   
		}
		else
		{
			while(t2>0)
			{
				if(cnt==1)
				{
					cnt=m+1;
				}
				if(a[--cnt]==0)
				{
					t2--;
				}
			}
			a[cnt]=1;
			printf("%d ",cnt);
		}
	}


	
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值