pku1012


既然题目中提到了约瑟夫环,就先考虑其规律
假设每个人都存储在数组中,a[0],a[1]...a[n-1],共有n个人,每次走m步,则第一轮出局的人坐标为(m-1)%n,第二轮的出局的人为(m-1+第一轮人出局的坐标)%(n-1)。。。。可以得到规律,第i轮出局的人坐标为f(i) = (m-1+f(i-1))%(n-i+1)。
回到原题,k个好人,k个坏人,先出去k个坏人,那么前k轮每轮出局的人的坐标都小于k。但如果从一开始,根据这个条件一个一个的测m值是否满足很明显太慢了。可以考虑所有m满足的共性。
假设剩下最后两个坏人,用g表示好人,b表示坏人,x表示这轮出列的坏人,则序列为:bbbbxg或bbbbgx,而下一轮肯定出去的是最后一个坏人,可以看到m满足条件:m%(k+1)  == 0或者m%(k+1) == 1。这样缩小了比较范围。
而此题不打表会超时的,代码如下:

#include<iostream>
#include<algorithm>
using namespace std;
int dabiao[14];
bool judge(int m,int k){
	int i = 1;
	int pos = 0;
	int temp;
	while( i<= k){
		temp = (m-1+pos)%(2*k-i+1);
		if(temp<k)
			return false;
		pos = temp;
		++i;
	}
	return true;
}
int joseph1(int k){
	int m = k+1;
	int result;
	while(true){
		if(judge(m,k)){
			result = m;
			break;
		}
		if(judge(m+1,k)){
			result = m+1;
			break;
		}
		m += (k+1);
	}
	return result;
}
int main()
{
	unsigned short k;
	int m;
	for(int k =1;k<14;++k){
		m = joseph1(k);
		dabiao[k] = m;
	}
	while(cin>>k){
		if(k == 0)
			break;
		cout<<dabiao[k]<<endl;
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值