代码改变世界

约瑟夫问题

2012-03-27 16:30  璋廊  阅读(933)  评论(0编辑  收藏  举报

Description

据传说,罗马人攻夺Jotapat后,Josephus和朋友两人与其他n个犹太人避难到一个洞穴里。使Josephus非常反感的是,他发现除了他自己和朋友外,其余的都决心殉难以免落入征服者的手中。他不敢太公然表示反对而只好同意了,但他坚持这一行动必须有条不紊地进行,并且建议大家坐成一圆圈,然后从洞口的人开始顺时针报数,数到m的人就杀掉,然后又从下一个人开始从1报数,直到最后一个人去自杀。问Josephus应该把自己和朋友放在第几个位置,才能避免被杀掉。注意:本题要求用链表实现。

Input

本题有多组测试数据,第一行是测试数据组数T,下面T行的每一行有两个用一个空格隔开的数n、m,表示犹太人数和报的数。其中1<=n<=99,1<=m<=999。

Output

输出共有T行,依次对应输入行。每行有两个数,从小到大排列,并用空格隔开。注意第二个数后没有空格。输出最后有一个空行。

Sample Input

 

1
2 2

 

Sample Output

 

1 3

 

Hint

位置是从洞口顺时针从1依次编号,报数也是从位置1的人顺时针报数。

/*********************************
建立循环链表,对于链表的删除和连接、:
**********************************/
#include<stdio.h>
#include<stdlib.h>
typedef struct point//建立结构体指针
{
	int data;
	struct point *next;
}Linkpoint,*LinkList;
int x,y;
LinkList built(int n)//建立循环链表:
{
	int i;
	LinkList head,p,s;
	p=head=(LinkList)malloc(sizeof(Linkpoint));
	head->data=1;
	for(i=2;i<=n+2;i++)
	{
		s=(LinkList)malloc(sizeof(Linkpoint));
		s->data=i;
		p->next=s;
		p=s;
	}
	p->next=head;
	return head;
}
void count(LinkList head,int m)//寻找地m个猴子,踢出去;
{
	int i=1;
	LinkList p,q;
	p=head;
	while(p->next!=p)
	{
		if(i==m-1)
		{
			q=p->next;//连接链表;
			p->next=q->next;
			x=q->data;
			free(q);
			i=1;
			p=p->next;
		}
		else {
			p=p->next;
			i++;
		}
	}
		y=p->data;
}
int main()
{
	int n,m,t;
	LinkList head;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d%d",&n,&m);
		if(m==1)
		{
			printf("%d %d\n",n+1,n+2);
			
		}
		else {
		head=built(n);
		count(head,m);
		if(x>y)
			printf("%d %d\n",y,x);
		else printf("%d %d\n",x,y);
		}
	}
	return 0;
}