c++约瑟夫环

1:

已知开始有n个数(从123...n)围在一个圆周围。从第1个开始报数,数到m的那个数时:

1)如果这个数x是偶数,就把这个数分裂成2x/2的数;

2)否则(x为奇数),则出列(删除这个数);

然后从下一个数开始又从1开始报数,数到m的那数又同上处理;依此规律重复下去,直到全部数出列。依次输出出列的数。

例如n=5,m=3

开始

1 2 3 4 5

输出3

1

1 2 4 5

输出1

2

2 4 5

输出5

3

2 4

4

1 1 4

输出1

5

1 4

6

1 2 2

7

1 2 1 1

输出1

8

1 2 1

9

1 1 1 1

输出1

10

1 1 1

输出1

11

1 1

输出1

12

1

输出1

说明:从红色的数开始,将数到黄色的位置

输入格式

第一行2个正整数NMN范围在[2,10000]M范围在[1,1000]

输出格式

一行,多个整数。

输入/输出例子1

输入:

5 3

输出:

3 1 5 1 1 1 1 1 1

#include<bits/stdc++.h>
using namespace std;
int n,k,m;
struct Tnode{  //节点的类型         
         int val;   //节点的数据 
         int next;  //下一个节点的位置 --数组下标 
};
Tnode a[1000005] ;  //存放节点的数组
int ap=0;        //数组a的空闲位置 
int head; //头指针 --- 第一个节点的位置(下标) 
 
//在下标为p的节点后面插入数值为x的新节点
void insert(int p, int x){
         int q=ap++;   //取得一个新节点
         a[q].val=x;     
         a[q].next = a[p].next;
         a[p].next = q;
} 
 
//下标为p的节点向后移动m个
int  nextM(int p, int m){
         while (m--)
            p=a[p].next;
         return p;
    }
//删除下标为p的节点后面的节点
void del(int p){
         a[p].next = a[ a[p].next].next;
}
void init(){
         //本题初始化 
         for (int i=1; i<=n; i++) {
                a[i].val = i;
                a[i].next = i+1;
           }
         a[n].next = 1;  //构成环         
         ap=n+1;  // 重要,容易漏!
}
int main()
{
         cin >> n  >> m;
         init();         
         //报数出队 
         int p=n;
         int count =n;
         while ( count>0 ) {
                   p=nextM(p, m-1 );  //p向后移动
                int q=a[p].next;
                   if (a[q].val%2==1){
                            cout << a[q].val<<" "; 
                            del(p);
                            count--;
                   } else {
                            int y=a[q].val/2;
                            a[q].val=y;   //分裂为一半 
                             insert(q,y);  //插入新节点
                            p=nextM(p,2); //到这2个节点后面 
                              count++;
                   }
         }        
         return 0;
} 

2:

已知开始有n个非零整数围在一个圆周围。从第1个开始:

1)如果这个数x是正数,就把这个数x删除,并向后移x个数;

2)否则(x为负数),就把这个数x删除,并向前移|x|个数;

然后从到达的数开始,依此规律重复下去,直到全部数出列。依次输出删除的数。

例如n=5,5个数为2 3 1 -1 1

开始

2 3 1 -1 1

输出2

1

3 1 -1 1

输出1

2

3 -1 1

输出-1

3

3 1

输出3

4

1

输出1

说明:从红色的数开始,将到达黄色的位置

输入格式

第一行1个正整数NN范围在[2,100000]

第二行N个非0整数,范围[-1000,1000]且不为0

输出格式

一行,N个整数。

输入/输出例子1

输入:

5

2 3 1 -1 1

输出:

2 1 -1 3 1

#include<bits/stdc++.h>
using namespace std;
struct Node{
    int val;
    int next;
    int pre;
}a[100001];
int n,ap=0;
void delNode(int p)
{
    a[a[p].pre].next=a[p].next;
    a[a[p].next].pre=a[p].pre;
}
void insert(int p,int x)
{
    int q=ap++;
    a[q].val=x;
    a[q].next=a[p].next;
    a[a[p].next].pre=q;
    a[q].pre=p;
    a[p].next=q;
}
int  nextM(int p, int m){
         while (m)
         {
            p=a[p].next;
             m--;
         }
         return p;
}
int  preM(int p, int m){
         while (m)
         {
            p=a[p].pre;
             m--;
         }
         return p;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int x;
        cin>>x;
        a[i].val=x;
        a[i].next=i+1;
        a[i].pre=i-1;
    }
    a[n].next=1;
    a[1].pre=n;
    int count=n;
    int p=1;
    while(count>0)
    {
        cout<<a[p].val<<" ";
            delNode(p);
            count--;
        if(a[p].val>0)
        {
            p=nextM(p,a[p].val);
        }
        else
        {
            p=preM(p,-a[p].val);
        }

    }
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪子小院

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值