Codeforces Round #633 (Div. 2) E. Perfect Triples (打表找规律)

E. Perfect Triples

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Consider the infinite sequence ss of positive integers, created by repeating the following steps:

  1. Find the lexicographically smallest triple of positive integers (a,b,c)(a,b,c) such that
    • a⊕b⊕c=0a⊕b⊕c=0, where ⊕⊕ denotes the bitwise XOR operation.
    • aa, bb, cc are not in ss.
    Here triple of integers (a1,b1,c1)(a1,b1,c1) is considered to be lexicographically smaller than triple (a2,b2,c2)(a2,b2,c2) if sequence [a1,b1,c1][a1,b1,c1] is lexicographically smaller than sequence [a2,b2,c2][a2,b2,c2].
  2. Append aa, bb, cc to ss in this order.
  3. Go back to the first step.

You have integer nn. Find the nn-th element of ss.

You have to answer tt independent test cases.

A sequence aa is lexicographically smaller than a sequence bb if in the first position where aa and bb differ, the sequence aa has a smaller element than the corresponding element in bb.

Input

The first line contains a single integer tt (1≤t≤1051≤t≤105) — the number of test cases.

Each of the next tt lines contains a single integer nn (1≤n≤10161≤n≤1016) — the position of the element you want to know.

Output

In each of the tt lines, output the answer to the corresponding test case.

Example

input

Copy

9
1
2
3
4
5
6
7
8
9

output

Copy

1
2
3
4
8
12
5
10
15

Note

The first elements of ss are 1,2,3,4,8,12,5,10,15,…1,2,3,4,8,12,5,10,15,…

题意:按照字典序,将三元组(x,y,z)依次排序(其中x^y^z==0,x

比如前几个三元组为

1 2 3

4 8 12

5 10 15

...

思路:其实打表出来明显是有规律的,但是不知道咋写。赛后看大佬们打出来了四进制的表,规律就很明显了(啊啊啊我怎么没想到)

四进制下:
//001 002 003
//1行  第一段 
//010 020 030
//011 022 033
//012 023 031
//013 021 032
//4行  第二段 
//100 200 300
//101 202 303
//102 203 301
//103 201 302
//110 220 330
//111 222 333
//112 223 331
//113 221 332
//120 230 330
//121
//……
//16行   第三段 

很明显三个数作为数列中的一项,每一段的第一个数以及段长都是公比为4的等比数列,然后再根据是三元组中哪一个数

①n%3==1,那么就是每三个数里面的第一个数,求一下每一段的第一项第一个数以及段内第几行加一下就行了

②n%3==2,可以看到在第二列中,减去该段的第一个数*2,每一位四进制都以0 2 3 1循环,加一下就行了

③n%3==0,可以看到在第三列中,减去该段的第一个数*3,每一位四进制都以0 3 1 2循环,加一下就行了

代码:

#include
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=400010;
const ll mo=998244353;
ll n,m,k;
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%lld",&n);
        ll p=1,m=n,sum=4;
        while(m>(sum-1)){
            sum<<=2;
        }
        sum>>=2;m=n-(sum-1);
        ll res=(m-1)/3;
        if(n%3==1) printf("%lld\n",sum+res);
        else if(n%3==2){
            ll ans=sum<<1;
            ll c=1;
            while(res){
                if(res%4==1) ans+=2*c;
                else if(res%4==2) ans+=3*c;
                else if(res%4==3) ans+=c;
                res>>=2;
                c<<=2;
            }
            printf("%lld\n",ans);
        }
        else if(n%3==0){
            ll ans=sum*3;
            ll c=1;
            while(res){
                if(res%4==1) ans+=3*c;
                else if(res%4==2) ans+=c;
                else if(res%4==3) ans+=2*c;
                res>>=2;
                c<<=2;
            }
            printf("%lld\n",ans);
        }
    }
    return 0;
}

 

你可能感兴趣的:(其他:思维)