[Codevs] 1282 约瑟夫问题

Posted Lev今天学习了吗

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Codevs] 1282 约瑟夫问题相关的知识,希望对你有一定的参考价值。

1282 约瑟夫问题

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 大师 Master
 
题目描述 Description

有编号从1到N的N个小朋友在玩一种出圈的游戏。开始时N个小朋友围成一圈,编号为I+1的小朋友站在编号为I小朋友左边。编号为1的小朋友站在编号为N的小朋友左边。首先编号为1的小朋友开始报数,接着站在左边的小朋友顺序报数,直到数到某个数字M时就出圈。直到只剩下1个小朋友,则游戏完毕。

现在给定N,M,求N个小朋友的出圈顺序。

 
输入描述 Input Description

唯一的一行包含两个整数N,M。(1<=N,M<=30000)

 
输出描述 Output Description

唯一的一行包含N个整数,每两个整数中间用空格隔开,第I个整数表示第I个出圈的小朋友的编号。

 
样例输入 Sample Input

5 3

 
样例输出 Sample Output

3 1 5 2 4

 

分析 Analysis

现在有一个标准的1-n的递增排列

击鼓传花,每次数到 m 时就要去掉当前这个元素,然后继续从 0 计数

那么定义 sum( i ) 为元素 i 之前的当前实际存在的元素数,在计算过程中,sum( i ) 才是真正的位置

那么给每一个元素一个初始权值 1 ,维护每个元素以自己为端点的前缀和,就能愉快的计算 sum( i ) 啦

那么设 pos 为当前要操作的元素位置,根据 AET(Apparently Easy Theory) 原理,我们知道下一步的 pos = (pos-1)%len

但是我们计算的时候要把pos+1

那么线段树的内容就是维护前缀和且单点置零啦

注意查找

这次的线段树被阉割的非常阉割

 

代码 Code

技术分享
 1 #include<cstdio>
 2 #include<iostream>
 3 #define mid (L+R)/2
 4 #define lc (rt<<1)
 5 #define rc (rt<<1|1)
 6 #define maxn 1000000
 7 using namespace std;
 8 
 9 int Tree[maxn],n,m;
10 void maintain(int rt){Tree[rt] = Tree[lc]+Tree[rc];}
11 void build(int rt,int L,int R){
12     if(L == R) Tree[rt] = 1;
13     else{
14         build(lc,L,mid);
15         build(rc,mid+1,R);
16         maintain(rt);
17     }
18 }
19 void modify(int rt,int L,int R,int pos){
20     if(L == R) Tree[rt] = 0;
21     else{
22         if(pos <= mid) modify(lc,L,mid,pos);
23         else modify(rc,mid+1,R,pos);
24         maintain(rt);
25     }
26 }
27 int query(int rt,int L,int R,int val,int remain){
28     if(L == R) return L;
29     else{
30         if(val <= Tree[lc]+remain) return query(lc,L,mid,val,remain);
31         else return query(rc,mid+1,R,val,remain+Tree[lc]);
32     }
33 }
34 
35 int main(){
36     scanf("%d%d",&n,&m);
37     
38     build(1,1,n);
39     
40     int pos = m,ans;
41     for(int i = n;i >= 1;i--){
42         pos = (pos-1)%(Tree[1]);
43 //        printf("###$$%d ",pos+1);
44         ans = query(1,1,n,pos+1,0);
45         printf("%d ",ans);
46         modify(1,1,n,ans);
47         pos += m;
48 //        getchar();
49     }
50     
51     return 0;
52 }
阉割的非常严重的线段树

以上是关于[Codevs] 1282 约瑟夫问题的主要内容,如果未能解决你的问题,请参考以下文章

AC日记——约瑟夫问题 codevs 1282

codevs1282约瑟夫问题

codves1282 约瑟夫问题 链表 会 T

OpenGL 着色器错误 1282

为啥调用 glLoadIdentity() 后出现 1282 错误?

glReadPixels 函数返回错误 1282 (GL_INVALID_OPERATION)