0
2

More than 3 years have passed since last update.

AtCoder Beginners Contest 過去問チャレンジ5

Last updated at Posted at 2019-12-31

AtCoder Beginners Contest 過去問チャレンジ5

ABC134D - Preparing Boxes

i = N から i を減らしながら順に確定していけば、特に難しいことはない.

N = int(input())
a = list(map(int, input().split()))

t = [0] * N
for i in range(N - 1, -1, -1):
    t[i] = (sum(t[2 * (i + 1) - 1::i + 1]) % 2) ^ a[i]

print(sum(t))
print(*[i + 1 for i in range(N) if t[i] == 1])

ABC080D - Recording

ぱっと見では imos 法一発に見えるのだが、S - 0.5 があるので、何も考えずに imos 法をすると、同じチャンネルの連続する録画が 0.5 の間だけ2台になってしまう罠.

解決法として一番簡単なのは、imos 法をやめてしまうこと. += 1 ではなく = 1 であればダブっても大丈夫だし、処理時間的にも実はぜんぜん大丈夫なのだった.

N, C = map(int, input().split())

tt = [[0] * (10 ** 5 + 1) for _ in range(C)]
for _ in range(N):
    s, t, c = map(int, input().split())
    for i in range(s - 1, t):
        tt[c - 1][i] = 1

ct = [0] * (10 ** 5 + 1)
for i in range(C):
    for j in range(10 ** 5 + 1):
        ct[j] += tt[i][j]

print(max(ct))

imos 法でやるのも難しくはないのだけど、エレガントに書こうと思うと意外と難しい. ソートして、連続してたら動きを変えるのが一番簡単か?

from operator import itemgetter

N, C = map(int, input().split())
stc = [list(map(int, input().split())) for _ in range(N)]
stc.sort(key=itemgetter(2, 0))

cs = [0] * (10 ** 5 + 1)
pt, pc = -1, -1
for s, t, c in stc:
    if pt == s and pc == c:
        cs[s] += 1
    else:
        cs[s - 1] += 1
    cs[t] -= 1
    pt, pc = t, c

for i in range(1, 10 ** 5 + 1):
    cs[i] += cs[i - 1]

print(max(cs))

ちなみに理論上はコケうるけど、そうそうヒットしないだろうとチャンネルをスルーしていたらしっかりとスナイプされました. 出題者、さすがやでえ…….

ABC121D - XOR World

f(A,B)f(0,A-1) xor f(0,B) と同じなので、g(N)=f(0,N) である、g が書ければ良い. 2進数の各桁ごとに1の数をカウントして、偶数か奇数かで処理ができる.

def h(A, n):
    if A == -1:
        return 0
    return A // (2 * n) * n + max(A % (2 * n) - (n - 1), 0)


def g(A):
    result = 0
    for i in range(48):
        t = 1 << i
        if h(A, t) % 2 == 1:
            result += t
    return result


def f(A, B):
    return g(A - 1) ^ g(B)


A, B = map(int, input().split())

print(f(A, B))

実のところ任意の偶数の n について n xor (n + 1)1 なので、各桁ごとにカウントする必要はない.

def g(A):
    t = ((A + 1) // 2) % 2  # 任意の偶数 n について n ^ (n + 1) == 1
    if A % 2 == 0:
        return A ^ t
    return t


def f(A, B):
    return g(A - 1) ^ g(B)


A, B = map(int, input().split())

print(f(A, B))

ABC117D - XXOR

Aの各ビット毎にビットの立っている数と立っていない数を集計し、立っている数のほうが多ければそのビットは0、立っていない数のほうが多ければそのビットは1のXを作ればいいだけ. ただ X には K 以下という条件がついているので、K を超えてしまったらビットを立てるのは諦める.

N, K = map(int, input().split())
A = list(map(int, input().split()))

bcs = [0] * 41
for i in range(N):
    a = A[i]
    for j in range(41):
        if a & (1 << j) != 0:
            bcs[j] += 1

X = 0
for i in range(40, -1, -1):
    if bcs[i] >= N - bcs[i]:
        continue
    t = 1 << i
    if X + t <= K:
        X += t

result = 0
for i in range(N):
    result += X ^ A[i]
print(result)

ABC094D - Binomial Coefficients

ai は最大の数. aj はその次に大きい数ではあるけど aiCaj == aiCai-aj なことに注意して次数を探す.

n = int(input())
a = list(map(int, input().split()))

a.sort()
x = a[-1]
b = [(min(e, x - e), e) for e in a[:-1]]
b.sort()
print(x, b[-1][1])

ABC098D - Xor Sum 2

加算は単調増加だけど、XOR は 1 xor 1 が 0 なので単調増加ではない. ところで 0 xor N == 0 + N なので「XOR <= 加算」となる. つまり一度でも XOR の結果が加算の結果未満になると、そこからどれだけ r の数字を増やしても永久に同じになることはない. また、ある l < r が同じ値の場合、l + 1 と r の組み合わせでも同じ値になる. ここまで来るとしゃくとり法でいいことが分かる.

N = int(input())
A = list(map(int, input().split()))

result = 0
r = 0
xs = A[0]
cs = A[0]
for l in range(N):
    while r < N - 1 and xs ^ A[r + 1] == cs + A[r + 1]:
        r += 1
        xs ^= A[r]
        cs += A[r]
    result += r - l + 1
    xs ^= A[l]
    cs -= A[l]
print(result)
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2