南邮 OJ 1190 约瑟夫问题

来源:互联网 发布:淘宝客不显示佣金 编辑:程序博客网 时间:2024/05/21 11:33

约瑟夫问题

时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte
总提交 : 577            测试通过 : 50 

比赛描述

约瑟夫问题是一个非常经典的问题,它的问题描述是:有 n 个人围成一圈,从第 1 个人开始,每次按顺时针方向向后选择第 m 个人,并将这个人出列。那么你能高效的算出出列的顺序吗?

输入

输入数据有多组,每组输入数据为一行,两个正整数 nm (1<=nm<=30000)

输出

每组输出只有一行,表示出列的顺序。每两个数字之间用一个空格分开。

样例输入

4 2
5 3

样例输出

2 4 3 1
3 1 5 2 4

提示

 

题目来源

李鸿斌(honghu)



#include<iostream>#define N 30000struct seg_tree{int l,r,m,num;}st[N*4];void build(long id,int l,int r){st[id].l = l;st[id].r = r;st[id].m = (l+r)>>1;st[id].num = r-l+1;if(l!=r){build(id<<1,l,st[id].m);build((id<<1)+1,st[id].m+1,r);}}int find_id(int k){//返回剩下的数字中第k个数的idint id = 1;while(st[id].l!=st[id].r){if(k<=st[id<<1].num){id <<= 1;}else{k -= st[id<<1].num;id = (id<<1)+1;}}return st[id].l;}void del(int k){//删除剩余数字钟的第k个数int id=1;while(st[id].l!=st[id].r){--st[id].num;if(k<=st[id<<1].num){id <<= 1;}else{k -= st[id<<1].num;id = (id<<1)+1;}}--st[id].num;return;}int main(){int n,m,k;while(scanf("%d%d",&n,&m)!=EOF){memset(st,0,sizeof(st));build(1,1,n);k = 1;while(st[1].num){k = (k+m-1);k %= st[1].num;if(k==0){k = st[1].num;}printf("%d",find_id(k));if(st[1].num!=1){putchar(' ');}del(k);}putchar('\n');}}






0 0
原创粉丝点击