题目描述
n 个人围成一圈,从第一个人开始报数,数到 m 的人出列,再由下一个人重新从 1 开始报数,数到 m 的人再出圈,依次类推,直到所有的人都出圈,请输出依次出圈人的编号。
输入格式
输入两个整数 n,m。
输出格式
输出一行 n 个整数,按顺序输出每个出圈人的编号。
输入输出样例
输入
10 3
输出
3 6 9 2 7 1 8 5 10 4
一.用结构体实现单向动态链表
#include<bits/stdc++.h>
using namespace std;
struct node{
int data;
node *next;
};
int main(){
int n,m;
scanf("%d%d",&n,&m);
node *head,*p,*now,*prev;
head=new node;
head->data=1;
head->next=NULL;
//分配节点一,值为1
now=head;
for(int i=2;i<=n;i++){
p=new node;
p->data=i;
p->next=NULL;
now->next=p;
now=p;
}
now->next=head;//最后一个指向第一个
//建立链表
now=head,prev=head;
while((n--)>1){
for(int i=1;i<m;i++){
prev=now;
now=now->next;
}
printf("%d ",now->data);
prev-> next=now->next;
delete now;
now=prev->next;
//输出并删除此元素
}
printf("%d",now->data);
delete now;
return 0;
}
二.用结构体数组实现单向静态链表
//用结构体数组实现单向静态链表
#include<bits/stdc++.h>
const int N=105;
struct node{
int id,nextid;
}nodes[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
nodes[0].nextid=1;
for(int i=1;i<=n;i++){
nodes[i].id=i;
nodes[i].nextid=i+1;
}
nodes[n].nextid=1;
int now=1,prev=1;
while((n--)>1){
for(int i=1;i<m;i++){
prev=now;
now=nodes[now].nextid;
}
printf("%d ",nodes[now].id);
nodes[prev].nextid=nodes[now].nextid;
now=nodes[prev].nextid;
}
printf("%d",nodes[now].nextid);
return 0;
}
三.用结构体数组结束双向静态链表
//用结构体数组结束双向静态链表
#include<bits/stdc++.h>
const int N=105;
struct node{
int id,preid,nextid;
}nodes[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
nodes[i].id=i;
nodes[i].preid=i-1;
nodes[i].nextid=i+1;
}
nodes[n].nextid=1;
nodes[1].preid=n;
int now=1;
while((n--)>1){
for(int i=1;i<m;i++)
now=nodes[now].nextid;
printf("%d ",nodes[now].id);
int prev=nodes[now].preid,next=nodes[now].nextid;
nodes[prev].nextid=nodes[now].nextid;
nodes[next].preid=nodes[now].preid;
now=next;
}
printf("%d",nodes[now].nextid);
return 0;
}
四.用一维数组实现单向静态链表
//用一维数组实现单向静态链表
#include<bits/stdc++.h>
int nodes[150];
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n-1;i++)
nodes[i]=i+1;
nodes[n]=1;
int now=1,prev=1;
while((n--)>1){
for(int i=1;i<m;i++){
prev=now;
now=nodes[now];
}
printf("%d ",now);
nodes[prev]=nodes[now];
now=nodes[prev];
}
printf("%d",now);
return 0;
}
五.用c++库中STL的list
//STL:list
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,m;
cin>>n>>m;
list<int>node;
for(int i=1;i<=n;i++)
node.push_back(i);
list<int>::iterator it=node.begin();//迭代器,.begin()首元素的指针,即node[0]的指针
while(node.size()>1){
for(int i=1;i<m;i++){
it++;
if(it==node.end())it=node.begin();//.end()末尾的下一个元素的指针,类似于空指针,不指向任何元素
}
cout<<*it<<" ";
list<int>::iterator next=++it;
if(next==node.end()) next=node.begin();
node.erase(--it);
it=next;
}
cout<<*it;
return 0;
}
六. 一般解法
#include<bits/stdc++.h>
using namespace std;
int n,m,next[1000005];
int main(){
cin>>n>>m;
for(int i=0;i<n;i++)
next[i]=i+1;
next[n]=1;
int p=0;
for(int i=1;i<=n;i++){
for(int j=1;j<m;j++)
p=next[p];//
cout<<next[p]<<" ";
next[p]=next[next[p]];
}
return 0;
}
七.数学解法
总人数S | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
活位置W | 1 | 1 | 3 | 1 | 3 | 5 | 7 | 1 | 3 | 5 | 7 | 9 | 11 | 13 | 15 | 1 | 3 | 5 | 7 |
不难看出:当S=+x(n,x均为自然数)时,
W=2x+n。
这里就留个作业,试试用数学来解这道题。