2016多校10 HDU 5860 Death Sequence

来源:互联网 发布:天龙八部有挂机软件 编辑:程序博客网 时间:2024/05/17 00:03

2016多校联合训练#10

HDU 5860 Death Sequence

递推,变形约瑟夫环(链)

传送门:HDU


题意

n个人站成一列,每次第1个,k+1个,2*k+1个……..出队,剩下人重新站成一队,继续这样出队,直到队里没人。q次查询,每次要查询第x个队的人在最开始队列的序号。


思路

  1. 把人从0开始编号,这样如果i%k==0,那么这个人一定是第一轮出队。

  2. 如果i%k!=0,那么这个人可以转移到编号是iik1的人,他的出队次序和编号是iik1的人一样,出队轮数是编号是iik1的人加1,因为上一轮已经有ik+1出来了。比如12个人,第一轮出来4个,分别是0,3,6,9;对于编号是10的人,他可以转移到编号是6的人身上。同理8转移到5,5转移到3。往前转移的过程实际就是出队人出去,剩下人重新编号的过程。写一下就明白了。

  3. 所以用结构体封装,封装初始编号n,出对轮数k,该轮出队次序m。重载小于号,按出队轮数-出对次序排序。这样最后sort,就可以对于询问以O1查询输出了。


代码

#include <iostream>#include <cstdio>#include <algorithm>#include <cstdlib>#include <cstring>#include <cmath>#include <vector>#include <queue>#include <stack>#include <iomanip>#include <string>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;const int MAXN=3000005;const int oo=1000000007;typedef long long int LL;struct number{    int n;    int k;    int m;    bool operator <(const number &a)const    {        if(k==a.k) return m<a.m;        else return k<a.k;    }};number a[MAXN];void deal(int n,int k){    int cnt=1;    for(int i=0;i<n;i++)    {        a[i].n=i;        if(i%k==0)        {            a[i].k=1;            a[i].m=cnt++;        }        else        {            a[i].k=a[i-i/k-1].k+1;            a[i].m=a[i-i/k-1].m;        }    }    sort(a,a+n);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n,k,q;        scanf("%d%d%d",&n,&k,&q);        deal(n,k);        while(q--)        {            int t;            scanf("%d",&t);            printf("%d\n",a[t-1].n+1);        }    }    return 0;}
0 0
原创粉丝点击