题目:
分析:
这道题目用链表来模拟整个过程,就只需要指针的移动和链表节点的删除两种操作就好了。首先新建一个足够长的链表表示长队,链表节点存的数据就是每个人的编号。然后用一个变量m来记录当前接受服务的人的编号,以后每数m次,就把该节点删除,因为不能接受服务的人直接离开,所以可以直接删除该节点。现在我们来讨论一下初始链表的长度。由于答案输出的最大编号不超过10000,所以链表的长度也不会超过10000。那么是不是链表的初始长度就为10000呢?答案是否定的。我们可以发现,第一个接受服务的人是2号,那么,也就是意味着在2号后面的所有偶数号码全部都要离开,而我们又可以确定2号是第一个被删除的,可以不用考虑,一起忽略,所以我们直接建一个全部存放奇数的链表,第一个节点的编号是3号,这样就能省掉一半的节点。注意到如果这样的话,那么我们应该要输出的是第n-1个接受服务的人的编号,因为2号就是第一个接受服务的人。另外,由于n最小为1,而二号又被我们忽略,所以要加一个判断,当n为1时,输出为2。然后通过实验,又可以发现,当n=1000时,输出结果为9863,那么也就是说最大编号为9863,这样又可以省下一些节点。
代码:
#include<iostream>
#include<stdlib.h>
using namespace std;
struct Node
{
int num;
Node *next;
};
int main()
{
Node *head, *p, *newp, *p1;
int i, j, n, m;
cin >> n;
head = (Node*)malloc(sizeof(Node));
head->next = NULL;
p = head;
for (i = 3; i<9864; ) //最大编号为9863
{
newp = (Node*)malloc(sizeof(Node));
newp->num = i ;
p->next = newp;
newp->next = NULL;
p = p->next;
i = i + 2; //偶数编号可以不考虑
}
for (i = 2; i<n; i++)
{
m = head->next->num; //记录当前接受服务的号数
p = head;
p1 = p->next;
p->next = p1->next; //删除当前接受服务的人
delete p1;
p = head;
while (p->next != NULL)
{
for (j = 0; j < m - 1; j++) //往后数m次
{
if (p->next == NULL)
break;
p = p->next;
}
if (p->next == NULL)
break;
p1 = p->next;
if (p1->next == NULL)
break;
p->next = p1->next; //删除第m个节点
delete p1;
}
}
if(n==1)
cout<<"2"<<endl; //n=1的情况
else
cout << head->next->num << endl;
return 0;
}