我们跑个暴力的dfs 把三元组按顺序找出来 然后找规律(很多时候打了表我也不知道有啥规律)
因为是异或操作 我们可以看二进制表 但是看四进制表可能更可以看出这个规律
1行(第一块)
001 002 003
4行(第二块)
010 020 030
011 022 033
012 023 031
013 021 032
16行(第三块)
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
。。。。。。。。
我们发现每一块(位数一样的我们视为一块)的行数分别是 1 4 16 64。。。。 那我们可以先找出询问的位置在哪一块 还可以找到它在哪一列
然后我们一个块一个块的看 我们发现第i块有i位四进制
最高位等于列数 第二高位似乎没什么规律
在第二块 我们发现 第一列的第二高位 是0 1 2 3 第二列是 0 2 3 1 第三列是 0 3 1 2
然后我们看第三块 第二高位的规律似乎变了 但是我们看最低位 第一列 是0 1 2 3 循环 第二列是 0 2 3 1循环 第三列是 0 3 1 2 循环 第一列的第二高位似乎是 4个0 4个1 4个2 4个3 循环 第二列和第三列也类似 这时候我们可以往后面再打几行 或者猜一个规律
这个规律就是 第一列的数 在最低位 是 0 1 2 3 循环 第二位是 4*(0 1 2 3) 循环 第三位是 16*(0 1 2 3) 循环以此类推
最高位保持和列数相同
第二列和第三列 分别是 0 2 3 1和 0 3 1 2 这样的循环方式
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll p4[33];
ll g[4][5];
int main(){
int t;
p4[0]=1;
g[1][0]=0,g[1][1]=1,g[1][2]=2,g[1][3]=3;
g[2][0]=0,g[2][1]=2,g[2][2]=3,g[2][3]=1;
g[3][0]=0,g[3][1]=3,g[3][2]=1,g[3][3]=2;
for(int i = 1; i <= 30; i++) p4[i]=p4[i-1]*4;
scanf("%d",&t);
while(t--){
ll n;
scanf("%lld",&n);
ll p = n/3+1,c = n%3;
if(!c) c=3,p--;
ll ct = 1,now = 1;
while(p>now){
p-=now;
ct++;
now*=4ll;
}
//printf("p=%lld c=%lld ct=%lld now=%lld\n",p,c,ct,now);
ll ans = 0;
p--;
ans+=c*p4[ct-1];
for(ll i = ct-1; i >= 1; i--){
ans+=g[c][(p/p4[i-1])%4]*p4[i-1];
}
printf("%lld\n",ans);
}
return 0;
}