1190_约瑟夫问题

约瑟夫问题

  • Description

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

  • Input

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

  • Output

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

  • Sample Input

4 2
5 3

  • Sample Output

2 4 3 1
3 1 5 2 4

 #include<iostream>
using namespace std;

#define R(r) ((r)<<1|1)
#define L(r) ((r)<<1)
#define Mid(x,y) (((x)+(y))>>1)
#define M 30000+10

struct tree
{
    int x,y,num;
}t[3*M];

void build(int x,int y,int r)
{
    t[r].x=x;
    t[r].y=y;
    t[r].num=y-x+1;
    if(x==y) return ;
    build(x,Mid(x,y),L(r));
    build(Mid(x,y)+1,y,R(r));
}
int find(int k,int r)
{
    t[r].num--;
    if(t[r].x==t[r].y) return t[r].x;
    if(k<=t[L(r)].num)
        return find(k,L(r));
    else
        return find(k-t[L(r)].num,R(r));
}

int main()
{
    int n,m,i,pre;
    while(scanf("%d%d",&n,&m)==2)
    {
        build(1,n,1);
        pre=((m%n)?m%n:n);
        printf("%d",find(pre,1));
        for(i=1;i<n;i++)
        {
            pre=(pre-1+m)%(n-i);
            pre=pre?pre:n-i;
            printf(" %d",find(pre,1));
        }
        puts("");
    }
    return 0;
} 

你可能感兴趣的:(1190_约瑟夫问题)