[ABC126F] XOR Matching 題解

PerchLootie發表於2024-06-07

很好的構造題。

題意

請構造一個長度為 $2^{m+1}$ 的序列 $a$,該序列滿足:

  • $\forall i \in[1, 2^{m+1}], a_i \in [0, 2^m-1]$ 且每個數都恰好出現兩次。
  • 對於任意一對 $(i, j)$ 滿足 $a_i = a_j$,$a_i\oplus a_{i+1} \oplus \cdots \oplus a_{j-1} \oplus a_j = k$。

$\oplus$ 表示按位異或。

思路

很顯然,當 $k>2^m-1$ 時無解。

再考慮平凡的的情況:

  • 當 $m$ 為 $0$,$k$ 為 $0$ 時,只有 0 0 一組解。
  • 當 $m$ 為 $1$,$k$ 為 $0$ 時,樣例告訴我們只有 0 0 1 1 一組解。
  • 當 $m$ 為 $1$,$k$ 為 $1$ 時,樣例告訴我們無解。

接下來考慮一般情況:

我們知道,$a \oplus a$ 為零,所以只需構造一個序列形如:

$$ 0,1 \dots 2m-1,k,2m-1 \dots 1,0,k $$

該式滿足:對於任意一對 $(i, j)$,$a_i = a_j$,$a_i\oplus a_{i+1} \oplus \cdots \oplus a_{j-1} \oplus a_j = k$。
顯然,這個序列除最後一個元素外是迴文的,並且所有數字都出現了 $2$ 次,正好可以相互抵消。
對於 $k$ 形成的子序列,有一個公式:$0\oplus 1 \oplus 2 \oplus \dots \oplus k=0$,因為在 $0$ 至 $k$ 的序列中,每一位上都出現了偶數個 $1$,全部抵消後便為 $k \oplus 0=k$。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,s,d[100005],f;
ll ans;
int main(){
    scanf("%lld%lld",&a,&s);
    if(a==1&&s==0){
        printf("0 0 1 1");
        return 0;
    } 
	if(s>=pow(2,a)){
		printf("-1");
		return 0;
	}
	for(int i=0;i<pow(2,a);i++){ 
		if(i==s) continue;
		printf("%lld ",i);
	}
	printf("%lld ",s);
	for(int i=pow(2,a)-1;i>=0;i--){ 
		if(i==s) continue;
		printf("%lld ",i);
	}
	printf("%lld",s);
    return 0;
}

相關文章