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;
}