Official

A - Flip Row or Col 2 Editorial by toam


\(M=\lfloor \frac{N-1}{4}\rfloor\) とします.

まず,\(1\) 行目がすべて \(0\) になるように適宜列 flip をしておきます.\(1\) 行目がすべて \(0\) である状態から列 flip できる箇所はちょうど \(R_1(\leq M)\) 個です.

各行について見ていきます.もし行に含まれる \(1\) の個数が \(N/2\) 以上だった場合,\(1\) の個数は列 flip によって最大でも \(M\) 個しか減らないため,行の総和を \(R_i\) にすることはできません(\(R_i\leq M\lt N/2-M\) であるため).したがって,行の総和が \(N/2\) 以上である場合はその行を flip してよいです.すべての行に対してこの処理が終わったら,これ以降で 行 flip する必要はありません.

次は各列について見ていきます.行 flip は行わないため,列 \(j\) の総和は \(C_j\) または \(N-C_j\) である必要があります.\(N-C_j\) のときは列 \(j\) を flip します.

これらの操作によって得られた \(A\) が各行の総和の条件を満たしているか判定すればよいです.

以上をまとめると,

  1. \(1\) 行目が全部 \(0\) になるように列 flip をする.
  2. 各行に対して,総和が \(N/2\) 以上であればその行を flip する.
  3. 各列に対して,総和が \(N/2\) 以上であればその列を flip する.
  4. 得られた行列が条件を満たすか判定する.

という手順でこの問題を解くことができます.計算量は \(O(N^2)\) です.

def solve():
    N = int(input())
    A = [[int(j) for j in input()] for i in range(N)]
    R = list(map(int, input().split()))
    C = list(map(int, input().split()))
    op_row = [0] * N
    op_col = [0] * N

    def flip_row(i):
        op_row[i] ^= 1
        for j in range(N):
            A[i][j] ^= 1

    def flip_col(j):
        op_col[j] ^= 1
        for i in range(N):
            A[i][j] ^= 1

    for j in range(N):
        if A[0][j] == 1:
            flip_col(j)
    for i in range(N):
        if sum(A[i]) >= (N + 1) // 2:
            flip_row(i)
    for j in range(N):
        if sum(A[i][j] for i in range(N)) >= (N + 1) // 2:
            flip_col(j)
    for i in range(N):
        if sum(A[i]) != R[i]:
            return print("No")
    for j in range(N):
        if sum(A[i][j] for i in range(N)) != C[j]:
            return print("No")

    print("Yes")
    print(*op_row, sep="")
    print(*op_col, sep="")


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

posted:
last update: