Counting-out Rhyme 约瑟夫环

                                                                Counting-out Rhyme                
Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u
Description

n children are standing in a circle and playing the counting-out game. Children are numbered clockwise from 1 to n. In the beginning, the first child is considered the leader. The game is played in k steps. In the i-th step the leader counts out ai people in clockwise order, starting from the next person. The last one to be pointed at by the leader is eliminated, and the next player after him becomes the new leader.

For example, if there are children with numbers [8, 10, 13, 14, 16] currently in the circle, the leader is child 13 and ai = 12, then counting-out rhyme ends on child 16, who is eliminated. Child 8 becomes the leader.

You have to write a program which prints the number of the child to be eliminated on every step.

Input

The first line contains two integer numbers n and k (2 ≤ n ≤ 1001 ≤ k ≤ n - 1).

The next line contains k integer numbers a1, a2, ..., ak (1 ≤ ai ≤ 109).

Output

Print k numbers, the i-th one corresponds to the number of child to be eliminated at the i-th step.

Sample Input

Input
7 5
10 4 11 4 1
Output
4 2 5 6 1 
Input
3 2
2 5
Output
3 2 

Hint

Let's consider first example:

  • In the first step child 4 is eliminated, child 5 becomes the leader.
  • In the second step child 2 is eliminated, child 3 becomes the leader.
  • In the third step child 5 is eliminated, child 6 becomes the leader.
  • In the fourth step child 6 is eliminated, child 7 becomes the leader.
  • In the final step child 1 is eliminated, child 3 becomes the leader.




可以利用双端队列和两个普通队列来完成。
1.双端队列的下标控制的比较简单,主要思想是将队头不用的放到队尾,遇到需要离队的弹出即可。优点是什么?自动形成一个有序的排列方式,比起用数组模拟少了控制数组下标的这一过程(这同样也是普通队列的优点)。其次便是形成了一个环,程序可以绕着这个环一直跑。

2.两个普通队列,主要思想是将两个队列看成两个容器A,B。先向容器A 里存最初始的数据,然后在“翻”A容器的时候,将翻出来的数据存到容器B,如此反复。这个方法比用数组好,但比起双端队列来很是笨重。
 
也就是说,如若一组数据是以环的方式且以一定的序列来循环的话,用双端队列。

下面是AC代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<deque>
using namespace std;
int main()
{
    deque<int> sh;
    int n,k,i,p,j,x,y;
    int q;
    scanf("%d %d",&n,&k);
    for(i=1;i<=n;i++)
        sh.push_back(i);
    for(q=1;q<=k;q++)
    {
        p=0;
        j=0;
        scanf("%d",&x);
        p=sh.size();
        x%=p;     //不断地循环其实有很多是重复的,x/(队列的长度)是绕着队列转了几圈,只需要找x%(队列的长度),即真正有用的查找。
        for(i=0;i>=-1;i++)
        {
            if(i==x)
            {
                y=sh.front();
                sh.pop_front();
                printf("%d ",y);
                break;
            }
            y=sh.front();
            sh.pop_front();
            sh.push_back(y);

        }
    }
    return 0;
}

下面这道题用的就是两个普通队列(太笨重了......)

                                                    约瑟夫环(栈和队列)
Time Limit:1000MS      Memory Limit: 1024000KB      64bit IO Format: %lld & %llu

Description

题目:n个数字(1,2,3…,n)形成一个圆圈,从数字1开始,每次从这个圆圈中删除第m个数字(第一个为当前数字本身,第二个为当前数字的下一个数字)。
当一个数字删除后,从被删除数字的下一个继续删除第m个数字。
求出在这个圆圈中剩下的最后一个数字。

Input

输入:

n=9

m=5

Output

The last one is 8

Sample Input

9 5

Sample Output

8

AC代码:

#include <iostream>
#include<stdio.h>
#include<stdlib.h>
#include<queue>
using namespace std;
int main()
{
    queue<int> first[2];
    int i,p,j,n,m;
    int x,y,w,e;
    int k;
    while(!first[0].empty())
        first[0].pop();
    scanf("%d %d",&n,&m);
    for(i=1; i<=n; i++)
        first[0].push(i);
    while(!first[1].empty())
        first[1].pop();
    p=0;
    w=0;
    e=0;
    for(i=0; i<=1; i++)
    {
        while(1)
        {
            k=first[i].size();
            if(++p==m&&k>=1)
            {
                first[i].pop();
                p=0;
            }
            else if(!first[i].empty())
            {
                x=first[i].front();
                if(i==0)
                    first[i+1].push(x);
                else
                    first[i-1].push(x);
                first[i].pop();
            }
            else if(first[i].empty())
            {
                p--;
                if(i==0)
                {
                    y=first[1].size();
                    if(y==1)
                        w=1;
                    break;
                }
                else
                {
                    y=first[0].size();
                    if(y==1)
                        w=1;
                    break;
                }
            }
        }
        if(w==1)
        {
            e=1;
            break;
        }
        if(i==1)
            i=-1;
    }
    printf("%d\n",x);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值