Codeforces 1339E Perfect Triples (找规律)
题意
构造了一个数组,其中每相邻三个数(a,b,c)为一组,满足a<b<c,且abc==0,数组字典序最小并且没有重复的数
1e5组询问,问你第n项是多少,n<=1e15
思路
果断打表,每组分开看,发现单看a是一个第i组开头为\(4^{i-1}\),长度为\(4^{i-1}\)的序列
而b的规律就比较难看了,由于题目中的异或可以想到打下二进制的表
发现b的二进制中每两位与对应的a的二进制每两位呈映射关系
a与b:0对应0,1对应2,2对应3,3对应1
然后对于每次询问我们只需要O(30)得到a的值,继而可以得到b,c
代码
这种规律我是想不到的
ll po[55];
ll s(int x){
if(x==0)return 0;
return (po[x]-1)/3;
}
int main(){
int t;
po[0]=1;
for(int i = 1; i <= 31; i++)po[i]=po[i-1]*4;
scanf("%d", &t);
while(t--){
ll n;
scanf("%lld", &n);
ll id = (n+2)/3;
ll now;
for(int i = 1; i <= 31; i++){
if((po[i]-1)/3>=id){
now=i;break;
}
}
ll x = po[now-1]+id-s(now-1)-1;
vector<int>v;
ll X = x;
while(X){
v.pb(X%4);X/=4;
}
ll y = 0;
reverse(v.begin(),v.end());
for(auto &xx:v){
if(xx==1)xx=2;
else if(xx==2)xx=3;
else if(xx==3)xx=1;
y*=4;y+=xx;
}
if(n%3==1){
printf("%lld\n",x);
}
else if(n%3==2){
printf("%lld\n",y);
}
else printf("%lld\n",x^y);
}
return 0;
}