Light OJ 1097 Lucky Number(线段树模拟)

来源:互联网 发布:欧树蜂蜜洁面凝胶 知乎 编辑:程序博客网 时间:2024/05/16 16:13

Lucky numbers are defined by a variation of the well-known sieve of Eratosthenes. Beginning with the natural numbers strike out all even ones, leaving the odd numbers 1, 3, 5, 7, 9, 11, 13, ... The second number is 3, next strike out every third number, leaving 1, 3, 7, 9, 13, ... The third number is 7, next strike out every seventh number and continue this process infinite number of times. The numbers surviving are called lucky numbers. The first few lucky numbers are:

1, 3, 7, 9, 13, 15, 21, 25, 31, 33, ...

In this problem your task is to find the nth lucky number where n is given in input.

Input

Input starts with an integer T (≤ 10000), denoting the number of test cases.

Each case contains an integer n (1 ≤ n ≤ 105).

Output

For each case, print the case number and the nth lucky number.

Sample Input

Output for Sample Input

2

2

100000

Case 1: 3

Case 2: 1429431

 

题意:题意就是让你构造一个数列,开始1~n,设此时数列中第i个数为ai,那么从当前数列每ai个数去除一个数
然后询问第几个数是多少。
分析:我们注意到上界为1429431,所以我们直接构造线段树模拟这一个过程即可。
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )const int INF=0x3f3f3f3f;typedef long long LL;const int maxn=1500000;int sum[maxn<<2];int n;void pushup(int rs){    sum[rs]=sum[rs<<1]+sum[rs<<1|1];}void build(int rs,int l,int r){    sum[rs]=0;    if(l==r)    {        sum[rs]=(l&1);        return ;    }    int mid=(l+r)>>1;    build(rs<<1,l,mid);    build(rs<<1|1,mid+1,r);    pushup(rs);}void update(int x,int l,int r,int rs){    if(l==r)    {        sum[rs]=0;        return ;    }    int mid=(l+r)>>1;    if(x<=sum[rs<<1]) update(x,l,mid,rs<<1);    else update(x-sum[rs<<1],mid+1,r,rs<<1|1);    pushup(rs);}int query(int x,int l,int r,int rs){    if(l==r)        return l;    int mid=(l+r)>>1;    if(x<=sum[rs<<1]) query(x,l,mid,rs<<1);    else query(x-sum[rs<<1],mid+1,r,rs<<1|1);}void init(){    build(1,1,1429431);    int pos=2;    while(sum[1]>=pos)    {        int val=query(pos,1,1429431,1);        int lit=sum[1];        int temp=val;        while(temp<=lit)        {            update(temp,1,1429431,1);            temp+=val-1;        }        pos++;    }}int main(){    init();    int t,n,cas=1;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        printf("Case %d: %d\n",cas++,query(n,1,1429431,1));    }}


0 0
原创粉丝点击