CF792B题解
kirky_wang · · 题解
题意
乍一看,不就是约瑟夫环吗?
实际上是这样的
一群编号为
普通版本
用一个数组标记数是否已经被删除,若被删除,扫的时候直接跳过。
要注意的是:因为测试数据给出的数是比较大的,所以要先进行求余,如果不这样做,就会超时
自己用的是数组实现,其实这样并不好,处理的时候很麻烦,看下面代码就知道了。......强烈建议用 STL。
代码
#include<iostream>
#include<string>
#include<algorithm>
#include<math.h>
#include<string.h>
using namespace std;
#define MAXN 105
bool del[MAXN];
int main()
{
int n,m;
int a;
int p;
while(cin>>n>>m)
{
p=2;//起点是1,所以从2开始数
int nn=n;
memset(del,false,sizeof(del));
while(m--)
{
cin>>a;
if(a%nn)a%=nn;//余数不为0时,求余
else if(a>nn)//余数为0且a>nn时,直接等于nn;
{
a=nn;
}
nn--;
while(1)
{
if(!del[p])
{
a--;
if(a==0)
{
del[p]=true;
break;
}
}
p++;
if(p>n)p=1;
}
if(m!=0)cout<<p<<" ";
else cout<<p;
while(del[p])//找起点
{
p++;
if(p>n)p=1;
}
//找起点的下一个数,因为是从起点的下一个数开始数的
p++;
if(p>n)p=1;
while(del[p])
{
p++;
if(p>n)p=1;
}
}
cout<<endl;
}
}
STL 版本
前置芝士:deque
deque 是 STL 的一个容器,全名为双端队列容器,具体定义方式和 vector 相似。
有两个重要函数,push_back(),pop_front(),前者可以向队尾插入元素,后者可以弹出(删除)队头元素。
我们可以通过向队尾插入队头元素后弹出(删除)队头元素,从而实现换一个人,即将这个‘圈’转一格。
用 deque 代码实现就是:
a.push_back(a.front());
a.pop_front();
这个弄好之后,其他就都好办了。直接看有没有出列,一个一个人旋转。
代码
#include<iostream>
#include<deque>
using namespace std;
deque<int> a;
int n,k;
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++)
{
a.push_back(i);
}//输入
for(int i=0;i<k;i++)
{
int s;
cin>>s;
s%=a.size();//注意要取模
while(s--)//一个一个旋转
{
a.push_back(a.front());//插入队首项
a.pop_front(); //弹出
}
int val=a.front();
a.pop_front();//out直接弹出
cout<<val<<" ";//输出
}
return 0;
}