【数据结构】P1996 约瑟夫问题
【题目链接】
https://www.luogu.org/problem/P1996
题目描述
n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……
依次类推,直到所有的人都出圈,请输出依次出圈人的编号.
输入格式
n m
输出格式
出圈的编号
输入输出样例
10 3
3 6 9 2 7 1 8 5 10 4
说明/提示
100 ≤ m,n ≤ 100
【题解】
问题其实并不困难,但是目的就是利用题目来锻炼自己的数据结构。
给出一题五解的做法。
【解法一】
利用STL里面的list,注意指针到了链表尾部要指回链表的头部。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m; int main()
{
list<int> List ;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) List.push_back(i);
list<int> ::iterator it = List.begin(),tmp; for(int i=;i<=n;i++){
for(int j=;j<m-;j++){
it++;
if( it == List.end() )
it = List.begin() ; } printf("%d ",*it);
tmp = it ;
it++;
if( it == List.end() ) it = List.begin() ;
List.erase(tmp);
}
return ;
}
STL——list
【解法二】
利用STL里面的queue,实现该过程,从队头出来,从队尾插入。
#include<cstdio>
#include<queue>
using namespace std;
int main()
{
int n,m;
queue<int> Q;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
Q.push(i);
}
for(int i=;i<=n;i++){
int cur = Q.front();
Q.pop();
for(int j=;j<m-;j++){ Q.push(cur);
cur = Q.front() ;
Q.pop();
}
printf("%d%c",cur,i==n?'\n':' ');
}
return ;
}
STL—queue
【解法三】
手工实现链表
#include<cstdio>
#include<queue>
#include<cstdlib>
using namespace std;
const int N = 1e5+; typedef struct Node{
int val ;
Node * next;
}Node;
Node *head , *tail , *tmp, *p ; int main()
{
int n,m;
head = new Node ;
head -> next = NULL ;
tail = head ;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
p = new Node ;
p -> val = i ;
p -> next = NULL ;
tail -> next = p ;
tail = p ;
} p = head -> next ;
tail -> next = head -> next; for(int i=;i<=n;i++){ for(int j=;j<m-;j++){
p = p->next;
}
printf("%d ",p->next->val);
tmp = p -> next ;
p -> next = tmp -> next ;
p = p -> next ;
free(tmp);
}
return ;
}
手工链表
【解法四】
手工实现队列
#include<cstdio>
#include<queue>
using namespace std;
const int N = 1e5+;
int main()
{
int n,m;
int Head = , Tail = ;
int Q[N];
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
Q[++Tail] = i ;
}
for(int i=;i<=n;i++){
int cur = Q[Head++];
for(int j=;j<m-;j++){
Q[++Tail] = cur ;
cur = Q[Head++];
}
printf("%d%c",cur,i==n?'\n':' ');
}
return ;
}
手工队列
【解法五】
这个题目最正解的做法是权值线段树,权值树状数组。
#include<iostream>
#include<cstdio> using namespace std; const int N=; int n,m; struct Stree
{
int l,r;
int dat;
}t[N<<];
//结构体 //建树
void build(int p,int l,int r)
{
t[p].l=l;t[p].r=r;
if(l==r)
{
t[p].dat=;
//初始化为1,表示这里是有人的
return;
}
int mid=(l+r)>>;
build(p<<,l,mid);
build(p<<|,mid+,r);
t[p].dat=t[p<<].dat+t[p<<|].dat;
} //把 x 踢出去
void change(int p,int x)
{
if(t[p].l==t[p].r)
{
t[p].dat=;
return;
}
int mid=(t[p].l+t[p].r)>>;
if(x<=mid) change(p<<,x);
else change(p<<|,x);
t[p].dat=t[p<<].dat+t[p<<|].dat;
} //查询 x 的位置
int query(int p,int x)
{
if(t[p].l==t[p].r)
return t[p].l;
//如果左边的剩余位置小于这个编号,那就在右边区域查找左边区域放不下的
if(x>t[p<<].dat) return query(p<<|,x-t[p<<].dat);
else return query(p<<,x);
} int main()
{
scanf("%d%d",&n,&m);
if(n==) return ;
build(,,n);
int pos=;
while(n)
{
pos=(pos+m-)%t[].dat+;//t[1].dat即剩余总人数
//先给 pos-1, 避免出现mod 完变成0的情况,mod完之后在 +1
//处理位置
// if(pos==0) pos=t[1].dat;
int qwq=query(,pos);
//查寻当前这个人的位置
cout<<qwq<<" ";
//输出
change(,qwq);
//踢出队伍
n--;
} return ;
}
//By Yfengzi
权值线段树
#include<iostream>
#include<cstdio>
using namespace std; const int maxn=3e4+;
int n,m,maxx;
int bit[maxn]; inline int lowbit(int x)
{
return x&-x;
}
inline void add(int pos,int x)
{
for(int i=pos;i<=maxx;i+=lowbit(i))bit[i]+=x;
}
inline int find_kth(int k)
{
int ans=,now=;
for(int i=;i>=;i--)
{
ans+=(<<i);
if(ans>maxx||bit[ans]+now>=k)ans-=(<<i);
else now+=bit[ans];
}
return ans+;
} int main()
{
scanf("%d %d",&n,&m);
maxx=n; //这里因为n后面会改变,所以先记录一下n的值。
for(int i=;i<=n;i++)bit[i]=lowbit(i);//这里完全等价于add(i,1),因为一开始都是1,所以bit[i]=i-(i-lowbit(i)+1)+1=lowbit(i)
int now=;//从1开始
while(n)
{
now=(now-+m-)%n+;//这里是小细节,本来的式子应该是(now+m-1)%n的,但是考虑如果只剩下2个元素,而我们当前要找的就是第二个元素呢?直接模就是0了,所以用一个+1 -1 的小操作更改取模运算的值域,这样就可以取到n的值了,而对别的无影响
int ans=find_kth(now);//找kth
add(ans,-);//把这个人删除
printf("%d ",ans);
n--;
}
return ;
}
权值树状数组
【数据结构】P1996 约瑟夫问题的更多相关文章
- P1996 约瑟夫问题
P1996 约瑟夫问题 广度优先搜索 我竟然寄几做对了 这个题用到了队列 下面详细解释: 我的代码: #include<iostream> #include<cstdio> # ...
- 【新知识】队列&bfs【洛谷p1996约瑟夫问题&洛谷p1451求细胞数量】
(是时候为五一培训准备真正的技术了qwq) part1 队列(FIFO) 算法简介: FIFO:First In First Out(先进先出) 队列是限定在一端进行插入,另一端进行删除的特殊线性表 ...
- [洛谷]p1996约瑟夫环 &xdoj1311
https://www.luogu.org/problemnew/show/P1996 约瑟夫环这个问题一直以来都是用循环链表写的,今天才知道有循环队列的写法.以下是要点: 1.循环队列实现环的思想, ...
- 洛谷——P1996 约瑟夫问题
P1996 约瑟夫问题 (什么?!要给学弟学妹讲约瑟夫问题?!难道就不怕我给他们讲错了吗?! 啊啊啊,为了不给学弟学妹们讲错,蒟蒻表示要临阵磨一下刀...) 题目背景 约瑟夫是一个无聊的人!!! 题目 ...
- 【vector的输出问题】 洛谷 P1996 约瑟夫问题
题目:P1996 约瑟夫问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 可恶啊,本来是一道不算难的题,硬是因为cin,cout同步流卡了我一天qwq 关闭cin,cout同步流 ...
- 洛谷P1996 约瑟夫问题【链表】
题目:https://www.luogu.org/problemnew/show/P1996 题意: 约瑟夫环.每次取出第m个,第2m个...... 思路: 链表维护.[感觉很少有用到链表.]非常经典 ...
- P1996 约瑟夫问题-题解(队列??明明是单循环链好吗)
一如既往的题目传送: https://www.luogu.org/problemnew/show/P1996 这里不讲数组模拟的方法(毕竟多做点题的模拟功力足以暴力出这道题),而是讲一种单循环 ...
- 【数据结构】约瑟夫问题 C语言链表实现
1.首先,我们先来了解一下什么是约瑟夫环问题: 讲一个比较有意思的故事:约瑟夫是犹太军队的一个将军,在反抗罗马的起义中,他所率领的军队被击溃,只剩下残余的部队40余人,他们都是宁死不屈的人,所以不愿投 ...
- 洛谷 P1996 约瑟夫问题
题目背景 约瑟夫是一个无聊的人!!! 题目描述 n个人(n<=100)围成一圈,从第一个人开始报数,数到m的人出列,再由下一个人重新从1开始报数,数到m的人再出圈,……依次类推,直到所有的人都出 ...
随机推荐
- CentOS 7.5 ——如何开放80、8080、3306等端口
CentOS 7.5 ——如何开放80.8080.3306等端口 ——说明:CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙——1.关闭firewall: s ...
- JavaWeb_(Mybatis框架)MyBatis整合Spring框架
MyBatis + Spring整合开发 a)使用Spring容器用单例模式管理Mybatis的sqlSessionFactory:b)使用Spring管理连接池.数据源等:c)将Dao/Mapper ...
- The problem is now the wait_for_fds() example function: it will call something like select(), poll() or the more modern epoll() and kqueue().
小结: 1.线程与惊群效应 Serializing accept(), AKA Thundering Herd, AKA the Zeeg Problem — uWSGI 2.0 documentat ...
- route按需加载的3种方式:vue异步组件、es提案的import()、webpack的require.ensure()
1. vue异步组件技术 vue-router配置路由,使用vue的异步组件技术,可以实现按需加载. 但是,这种情况下一个组件生成一个js文件.举例如下: { path: '/promisedemo' ...
- 自定义msi安装包的执行过程
有时候我们需要在程序中执行另一个程序的安装,这就需要我们去自定义msi安装包的执行过程. 比如我要做一个安装管理程序,可以根据用户的选择安装不同的子产品.当用户选择了三个产品时,如果分别显示这三个产品 ...
- 西湖论剑2019部分writeup
做了一天水了几道题发现自己比较菜,mfc最后也没怼出来,被自己菜哭 easycpp c++的stl算法,先读入一个数组,再产生一个斐波拉契数列数组 main::{lambda(int)#1}::ope ...
- Queue class
#pragma once#include <iostream>#include <iomanip> using namespace std; class Queue{ stru ...
- 22 Flutter仿京东商城项目 inappbrowser 加载商品详情、保持页面状态、以及实现属性筛选业务逻辑
加群452892873 下载对应21可文件,运行方法,建好项目,直接替换lib目录,在往pubspec.yaml添加上一下扩展. cupertino_icons: ^0.1.2 flutter_swi ...
- .net framework 4.0 安装失败解决办法
方法一 1.打开cmd命令窗口 运行net stop WuAuServ 停止更新服务 2.开始----运行------输入%windir% 3.找到SoftwareDistribution的 ...
- 分JOB实例
*&---------------------------------------------------------------------* *& Form F_SET_JOB * ...