公式

B - Adjacent Replace 解説 by evima


The sequence is 0-indexed.

First, let’s consider what numbers can be created when \(A=(2^0,2^1,2^2,\ldots,2^{N-1})\). Obviously, they are less than \(2^N\).

In fact, among non-negative integers less than \(2^N\), all numbers except \(2^0\oplus 2^2\oplus 2^4\oplus\ldots\) and \(2^1\oplus 2^3\oplus 2^5\oplus\ldots\) can be created.


(Proof)

Let \(s\) be the binary string of length \(N\) representing the number \(K\) to be created (\(K=\sum_{i=0}^{N-1} s_i2^i\)).

[1] When there exists \(i\) such that \(s_i=s_{i+1}=0\)

First, perform the operation at position \(i\) twice to make \(A_i=A_{i+1}=0\). Then, we aim to collect all positions to the left of \(i\) where \(s_j=1\) into position \(i+1\). That is, we operate to make \(A_{i+1}=\sum_{j=0}^{i-1}s_j2^j\). This can be done by looking at \(j\) in descending order and operating as follows:

  • If \(s_j=0\), do nothing.
  • If \(s_j=1\), first operate \(j+1,j+1,j+2,j+2,\ldots,i-1,i-1\) to make \(A_{j+1},A_{j+2},\ldots,A_i\) all \(0\), then operate \(j,j+1,\ldots,i\) to set \(A_{i+1}\leftarrow A_{i+1}\oplus A_j(=A_{i+1}\oplus 2^j)\).

Do the same thing for the right side of \(i+1\). First, move the created \(A_{i+1}\) to \(A_0\) through appropriate operations. Then, by doing the same thing as above, all elements on the right side of \(i+1\) can be moved to \(A_0\). This way, we can make \(A_0=K\).

[2] When there exists \(i\) such that \(s_i=s_{i+1}=1\)

  • When \(s_{i+2}=1\)
    By operating \(i,i+1\), we can make \(A_{i+2}\leftarrow A_i\oplus A_{i+1}\oplus A_{i+2}\), reducing to the case \(s_i=s_{i+1}=0\).

  • When \(s_{i+2}=0\)
    By operating at \(i\), we can make \(A_{i}\leftarrow A_i\oplus A_{i+1}\), reducing to the case \(s_{i+1}=s_{i+2}=0\).

(When \(i+2=N\), do the same thing for \(i-1,i,i+1\).)

[3] In other cases

\(s\) is either 010101... or 101010.... No matter how we perform the initial operation, bits included in \(K\) and bits not included will always coexist, making it impossible.


Thus, we have solved the case when \(A=(2^0,2^1,2^2,\ldots,2^{N-1})\). The number of operations is \(O(N^2)\), which is well within the operation limit.

For the general case of \(A\), it suffices to determine whether the following set \(S\subset \lbrace0,1,\ldots,N-1\rbrace\) exists:

  • \(\displaystyle\bigoplus_{i\in S}A_i=K\)
  • \(S\neq \lbrace 0,2,4,\ldots\rbrace\wedge S\neq \lbrace 1,3,5,\ldots\rbrace\)

Without the second condition, such \(S\) can be found using Gaussian elimination.

For finding \(S\) considering the second condition, there are, for example, the following two approaches:

  1. Since there must exist \(j\) satisfying \(j\in S\land j+1\in S\) or \(j\notin S\land j+1\notin S\), we can enumerate all such \(j\) and check them. The time complexity is \(O(N^2\log(\max A))\).
  2. First, ignore the second condition temporarily and find one \(S'\) such that the XOR equals \(K\). If this satisfies the second condition, we’re done. Otherwise, by trying at most \(2\) vectors from the solution space and taking XOR with \(S'\), we can find \(S\) that satisfies the second condition. The time complexity is \(O(N\log(\max A))\).
def find(N, K, A):
    no_base = [0]
    base = []

    def calc(v):
        bit = 0
        for x, y in base:
            if v ^ x < v:
                v ^= x
                bit ^= y
        return (v, bit)

    for i in range(N):
        v, bit = calc(A[i])
        if v > 0:
            base.append((v, bit ^ (1 << i)))
        else:
            no_base.append(bit ^ (1 << i))

    v, bit1 = calc(K)
    if v != 0:
        return []

    ng0, ng1 = sum(1 << i for i in range(0, N, 2)), sum(1 << i for i in range(1, N, 2))
    for bit2 in no_base:
        bit = bit1 ^ bit2
        if bit not in [ng0, ng1]:
            return [(bit >> i) & 1 for i in range(N)]
    return []


def solve():
    N, K = map(int, input().split())
    A = list(map(int, input().split()))
    S = find(N, K, A)
    if len(S) == 0:
        return print("No")
    p = -1
    for i in range(N - 2, -1, -1):
        if S[i] == S[i + 1]:
            p = i

    if S[p] == S[p + 1] == 0:
        op = [p, p]
    else:
        if p != N - 2:
            if S[p + 2] == 1:
                op = [p, p + 1, p, p]
            else:
                op = [p, p + 1, p + 1]
                p += 1
        else:
            op = [p, p - 1, p - 1]
            p -= 1

    for i in range(p - 1, -1, -1):
        if S[i]:
            for j in range(i + 1, p):
                op += [j, j, j - 1]
            op += [p - 1, p]
    for i in range(p - 1, -1, -1):
        op += [i, i, i + 1, i]
    for i in range(p + 2, N):
        if S[i]:
            for j in range(i - 2, 0, -1):
                op += [j, j, j + 1]
            op += [1, 0]

    print("Yes")
    print(len(op))
    print(*[i + 1 for i in op])


T = int(input())
for _ in range(T):
    solve()

投稿日時:
最終更新: