CodeForces_1338C Perfect Triples(数论)

Perfect Triples

time limit per test:2 seconds
memory limit per test:256 megabytes

Problem Description

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

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

You have to answer t independent test cases.

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

Input

The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 5 1≤t≤10^5 1t105) — the number of test cases.

Each of the next t lines contains a single integer n n n ( 1 ≤ n ≤ 1 0 16 1≤n≤10^{16} 1n1016) — the position of the element you want to know.

Output

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

Sample Input

9
1
2
3
4
5
6
7
8
9

Sample Output

1
2
3
4
8
12
5
10
15

题意

有序列S,初始为空,进行以下操作:
1:选择三元组(a,b,c)满足a^b^c==0,且a,b,c未在S中出现过,且a,b,c字典序最小。
2:将a,b,c依次放入序列S的尾部。
3:重复第一步。
求序列S的第n个数。

题解:

打表可以发现每个三元组a在一些段是连续的,依次为1~1,4~7,16~31…,
起始位置为 2 2 ∗ k 2^{2*k} 22k k k k为非负整数,且 [ 2 2 ∗ k , 2 2 ∗ k + 2 ) [2^{2*k},2^{2*k+2}) [22k,22k+2)的所有数都分布a为 [ 2 2 ∗ k , 2 2 ∗ k + 1 ) [2^{2*k},2^{2*k+1}) [22k,22k+1)的三元组内。
分析其中连续的几组三元组可以发现,将二进制下两位作为一组,规律如下:

a b c
00 00 00
01 10 11
10 11 01
11 01 10

根据n求出其所在三元组的a,然后根据上面的关系求出b,异或后可知c,n对3取余输出即可。

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define dbg(x) cout<<#x<<" = "<
#define INF 0x3f3f3f3f
#define eps 1e-7
 
using namespace std;
typedef long long LL;   
typedef pair<int, int> P;
const int maxn = 110000;
const int mod = 998244353;
LL d[64];
void solve(LL a, LL &b, LL &c);
 
int main()
{
    int t, i, j, k;
    LL n, a, b, c;
    for(i=0;i<29;i++)
        d[i] = 1LL<<(2*i);
    scanf("%d", &t);
    while(t--)
    {
        scanf("%I64d", &n);
        for(i=0;;i++)
            if(d[i]<=n && d[i+1]>n)break;
        a = d[i]+(n-d[i])/3;
        solve(a, b, c);
        if(n%3 == 1)printf("%I64d\n", a);
        else if(n%3 == 2)printf("%I64d\n", b);
        else printf("%I64d\n", c);
    }
    return 0;
}
 
void solve(LL a, LL &b, LL &c)
{
    b = 0;
    char str1[64], str2[64];
    for(int i=60;i>=0;i--){
        if(a&(1LL<<i))str1[i] = 1;
        else str1[i] = 0;
    }
    for(int i=59;i>=1;i-=2){
        if(str1[i] == 0 && str1[i-1] == 0)str2[i]=str2[i-1]=0;
        else if(str1[i]==0 && str1[i-1]==1)str2[i]=1,str2[i-1]=0;
        else if(str1[i]==1 && str1[i-1]==0)str2[i] = str2[i-1] = 1;
        else str2[i]=0,str2[i-1]=1;
    }
    for(int i=0;i<60;i++)
    if(str2[i])
        b |= 1LL<<i;
    c = a^b;
}

你可能感兴趣的:(数论)