1. 程式人生 > 實用技巧 >[CF1338C] Perfect Triples - 找規律

[CF1338C] Perfect Triples - 找規律

Description

按照如下方式構造一個無窮數列 \(S\)。選取一個字典序最小的三元組 \((a,b,c)\) 滿足 \(a,b,c \notin S\),並且 \(a \oplus b \oplus c = 0\),將 \(a,b,c\) 依次加入到序列 \(S\) 末尾。給定 \(n\) 求數列的第 \(n\) 項。

Solution

觀察到,三個成組,答案可以分為若干段,第 \(i \ge 0\) 的長度為 \(4^{i-1}\)

設當前組的開頭數字為 \(B\),則 \(B \sim B+4^{i-1}-1\) 都是分配給 \(a\) 的,\(B \sim B+4^{i-1} \sim B + 2 \times 4^{i-1} - 1\)

都是分配給 \(b\) 的,\(c\) 可以偷懶用 \(a,b\) 求出。

為了求 \(b\),可以將當前區間分成四段,分別取第 \(1,3,4,2\) 小的 \(B \sim B+4^{i-1} \sim B + 2 \times 4^{i-1} - 1\) 劃分成四段後的子區間,然後遞迴分治下去,直到求出。

其實 \(c\) 也可以用類似 \(b\) 的方法直接求出,只要把順序換成 \(1,4,2,3\) 即可。

當然也可以不遞迴,直接寫入二進位制各位的值。

#include <bits/stdc++.h>
using namespace std;

#define int long long 
const int N = 1000005;

const int k[3][4]={{0,1,2,3},{0,2,3,1},{0,3,1,2}};

void solve()
{
    int n;
    cin>>n;
    int group=(n-1)/3-1, type=(n-1)%3;
    int ans=0,bas=1;
    while(group>=0)
    {
        ans+=bas*k[type][group%4];
        group=group/4-1;
        bas*=4;
    }
    cout<<ans+bas*(type+1)<<endl;
}

signed main()
{
    int t;
    cin>>t;
    while(t--)
    {
        solve();
    }
}