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:
- 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.
- Append aa, bb, cc to ss in this order.
- 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<y<z,已经出现过的数不能再次出现),再依次标号,问你第n(n<=1e16)个数是多少
比如前几个三元组为
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<bits/stdc++.h>
#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;
}