NOI 3.2 1748:约瑟夫问题

题目来源:http://noi.openjudge.cn/ch0302/1748/

1748:约瑟夫问题

总时间限制1000ms  内存限制65536kB

描述

约瑟夫问题:有n只猴子,按顺时针方向围成一圈选大王(编号从1到n),从第1号开始报数,一直数到m,数到m的猴子退出圈外,剩下的猴子再接着从1开始报数。就这样,直到圈内只剩下一只猴子时,这个猴子就是猴王,编程求输入n,m后,输出最后猴王的编号。

输入

每行是用空格分开的两个整数,第一个是 n, 第二个是m ( 0 < m,n <=300)。最后一行是:

0 0

输出

对于每行输入数据(最后一行除外),输出数据也是一行,即最后猴王的编号

样例输入

6 2
12 4
8 3
0 0

样例输出

5
1
7

-----------------------------------------------------

思路

方法一:模拟法

用数组模拟报数过程,复杂度O(mn)

方法二:递推法

f[n]: n个人(0~(n-1)编号)m报数时的猴王

n个人选猴王,第一轮报数后,编号为m-1的人退出。此时令编号为m,m+1,m+2,…,n-1,0,…,m-1编号变为0,1,2,…,n-2, 则从第二轮报数开始,问题转化为n-1个人选猴王问题,此时猴王的人选并没有变,只是编号相应地减小了m而已。故n人选出的猴王编号为n-1人新序列里猴王编号+m.

f[n] = (f[n-1] + m) % n

-----------------------------------------------------

代码

 方法一:模拟法

// 模拟法,用数组模拟报数的过程
// 复杂度O(mn)

#include
#include
#include
using namespace std;

const int NMAX = 305;
int n,m;
int a[NMAX] = {};

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin ("0302_1748.txt");
	int i,cnt=n,p=0;
	while (	fin >> n >> m )
	{
		if (n==0 && m==0)
		{
			break;
		}

		if (n==1)
		{
			cout << 1 << endl;
			continue;
		}
		else if (m==1)
		{
			cout << n << endl;
			continue;
		}
		else if (n==2 && m==2)
		{
			cout << 1 << endl;
		}

		cnt = n;
		p = m;
		memset(a, 0, sizeof(a));
		while (cnt>1)
		{
			a[p] = 1;
			cnt--;
			for (i=0; i> n >> m )
	{
		if (n==0 && m==0)
		{
			break;
		}

		if (n==1)
		{
			cout << 1 << endl;
			continue;
		}
		else if (m==1)
		{
			cout << n << endl;
			continue;
		}
		else if (n==2 && m==2)
		{
			cout << 1 << endl;
		}

		cnt = n;
		p = m;
		memset(a, 0, sizeof(a));
		while (cnt>1)
		{
			a[p] = 1;
			cnt--;
			for (i=0; i

方法二:递推法

// 递推
// f[n]: n个人(0~n-1)m报数出列时猴王的编号
// f[n] = (f[n-1]+m)%n
// 复杂度O(n)

#include
#include
using namespace std;

int main()
{
#ifndef ONLINE_JUDGE
	ifstream fin ("0302_1748.txt");
	int n,m,i,ans;
	while (fin >> n >> m)
	{
		if (n==0 && m==0)
		{
			break;
		}
		if (n==1)
		{
			cout << 1 << endl;
			continue;
		}
		ans = 0;
		for (i=2; i<=n; i++)
		{
			ans = (ans+m)%i;
		}
		cout << ans+1 << endl;
	}
	fin.close();
#endif
#ifdef ONLINE_JUDGE
	int n,m,i,ans;
	while (cin >> n >> m)
	{
		if (n==0 && m==0)
		{
			break;
		}
		if (n==1)
		{
			cout << 1 << endl;
			continue;
		}
		ans = 0;
		for (i=2; i<=n; i++)
		{
			ans = (ans+m)%i;
		}
		cout << ans+1 << endl;
	}
#endif
}


你可能感兴趣的:(NOI)