Codeforces Round#633(Div.2)E.パーフェクトトリプル

E.パーフェクトトリプル

タイトルリンク

トピックの要約:

無限配列\(s \)があります。(空から開始)
辞書順で3つの最小数を見つけるたびに、\((a、b、c)\)は次の条件を満たす。

  • \(a \ oplus b \ oplus c = 0 \)
  • \(a、b、c \ notin s \)
    \(t \)回、毎回配列内の項目数を尋ねます\(n \)

アイデア:

テーブルをプレイした後、トリプルの最初の項目は常に\(4 ^ x \)の後に連続する番号であることがわかりましたこのようにして、2ビットの下で2ビットを転送しようとします
(つまり、4進数で、XORを便利に見せるために、このように説明します)。
各2ビットが取ることができる値は\(00、01、10、11 \)です。
最初に、\(1 \から4 ^ n-1 \)の数が使い果たされたと想定します。次に、\(4 ^ n \から4 ^ {n + 1} -1 \)を考えます。\(a <b <c \)
を取得するには、最上位の2 \(01、10、11 \)のみにする必要があります。つまり、\(a、b、c \)最上位の2 桁は互いに異なります。最初の2つがわかったので、続けて見下ろします。最初に、サンプルで指定された項目(バイナリ)を次の表の形式で示します。

\(a \) \(b \) \(a \ oplus b \)
\(00 \) \(00 \) \(00 \)
\(01 \) \(10 \) \(11 \)
\(10 \) \(11 \) \(01 \)
\(11 \) \(01 \) \(10 \)

4進数で(2桁単位)、すべての値が上記の条件を満たしていると大胆に推測します。

  • 2桁の場合、\((a、b、c)\)に\(1,2,3 \)しかなく、これは明らかに満足されます。
  • \(a、b、c \)\(2k \)ビットで満たされていると仮定して\(2k + 2 \)ビットを確認します。
    まず、この\(2k \)ビットを左に2つシフトします(いずれかを設定します)値のペアは\(pa、pb、pc \)、明らかに\(pa \ oplus pb = pc \))です。最小の辞書式順序の場合、最初に\(a \)
    \(00 \):を検討します\(pa + 00、pb + 00、pc + 00 \)が確立されました。
    \(01 \)\(b \)の場合、\(00、01 \)は真ではありません(\(b、c \)が繰り返されます)、それから\(pa + 01、pb + 10、pc + 11 \)
    ...
    残りのハンドでは、上の表が実際に満足していることがわかります。

長い我々はれるように決意として(N- \)\数が属するトリプル\((A、B、C )\) \(A \) この値を決定します。

コード:

#include "iostream"
#include "stdio.h"
#include "string.h"
#include "algorithm"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
const int N=1e6+5;
const ll mod=998244353;
const double eps=1e-5;
//const double pi=acos(-1);

#define ls p<<1
#define rs p<<1|1
ll f[3][4]={{0,3,1,2},{},{0,2,3,1}};
void solve(ll x,int y)
{
    if(y==1)
    {
        printf("%lld\n",x);
        return;
    }
    ll ans=0,p=1;
    while(x)
    {
        ans=ans+f[y][x%4]*p;
        x>>=2;
        p<<=2;
    }
    printf("%lld\n",ans);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int _;
    ll n;
    cin>>_;
    while(_--)
    {
        cin>>n;
        ll j=1,a;
        while(j<=n) j<<=2;
        j>>=2;
        if(j+2>=n) a=j;
        else a=j+(n-j)/3;
        solve(a,n%3);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/Suiyue-Li/p/12693020.html