def main():
H, W = map(int, input().split())
world = OneDimensionMap(H, W, 0)
for pos in world.allPosition():
if world.mapdata[pos] == 35:
start = pos
break
corner = set()
visited = set()
DIR4 = world.dir4()
def visit(pos):
visited.add(pos)
x, y = divmod(pos, W)
for xy in [(x, y), (x + 1, y), (x, y + 1), (x + 1, y + 1)]:
if xy in corner:
corner.remove(xy)
else:
corner.add(xy)
for dir in DIR4:
newpos = pos + dir
if world.mapdata[newpos] == 35 and newpos not in visited:
visit(newpos)
visit(start)
print(len(corner))
公式解説を見るともっとシンプルに書けることがわかる。
なければ足して、あれば取る、というのは要するに「処理が行われた回数が奇数回か?」ということと同値
それが知りたいだけなら、足し算の順序は入れ替えても同じなので隣接順に処理する必要はない
これでAC
python
def main():
H, W = map(int, input().split())
world = OneDimensionMap(H, W, 0)
from collections import defaultdict
cornerCount = defaultdict(int)
for pos in world.allPosition():
if world.mapdata[pos] == 35:
for d in [0, 1, W, 1 + W]:
cornerCount[pos + d] += 1
print(sum(v % 2 for v in cornerCount.values()))
def main():
N, M = map(int, input().split())
from collections import defaultdict
INF = 9223372036854775807
edges = defaultdict(lambda: defaultdict(lambda: INF)) # (1)
for _i in range(M):
frm, to, cost = map(int, input().split())
# -1 for 1-origin vertexes
edges[frm-1][to-1] = min(edges[frm-1][to-1], cost) # (2)
dist = []
for start in range(N):
dist.append(one_to_all(start, N, edges, INF=INF)) # (3)
for i in range(N):
x = INF
for j in range(N):
if j == i:
x = min(x, edges[i][i]) # (4)
else:
x = min(x, dist[i][j] + dist[j][i])
if x == INF:
print(-1)
else:
print(x)
def main():
from math import gcd
N = int(input())
AS = list(map(int, input().split()))
minA = min(AS)
ALL = set(AS)
NEW = set(AS)
while NEW:
next = set()
for x in ALL:
for y in NEW:
next.add(gcd(x, y))
ALL.update(NEW)
NEW = next - ALL
ret = 1
for x in ALL:
if x < minA:
ret += 1
print(ret)
公式解説
\exists (S \subset A) x = \gcd(S) \iff \gcd(y[x\text{ divides }y] ) = x
ある集合Sについて成り立つなら、そこにxの倍数を追加しても成り立つ
なのですべての部分集合をケアする必要はない
xの倍数であるものを全部含んだ集合だけを考えれば良い
xがAのどの数の約数でもない場合、集合が空になるので考えなくて良い
なのでいずれかの数の約数であるxについて、それと1対1対応する集合のgcdを取れば良い
約数個数は対数オーダーなのでAが10^9でも問題ない
それでも3TLE
約数の数が多いテストケースで落ちるようになる
python
def main():
from math import gcd
from functools import reduce
N = int(input())
AS = list(map(int, input().split()))
minA = min(AS)
S = set(AS)
divisors = set()
for x in S:
divisors.update(get_divisors(x))
ret = 1
for d in sorted(divisors):
if d == minA:
break
targets = [x for x in S if x % d == 0]
if reduce(gcd, targets) == d:
ret += 1
print(ret)
約数列挙のタイミングでgcdまで計算すればAC
python
def main():
from math import gcd
from collections import defaultdict
N = int(input())
AS = list(map(int, input().split()))
minA = min(AS)
S = set(AS)
gcds = defaultdict(int)
for x in S:
for d in get_divisors(x):
gcds[d] = gcd(gcds[d], x)
ret = 1
for d in sorted(gcds):
if d == minA:
break
if gcds[d] == d:
ret += 1
print(ret)
def main_simple():
from math import floor, ceil, sqrt
X, Y, R = map(float, input().split())
ret = 0
for y in range(floor(Y - R), ceil(Y + R) + 1):
xcep = R ** 2 - (y - Y) ** 2
a = 1
b = -2 * X
c = X ** 2 - xcep
e = b * b - 4 * a * c
if e < 0:
continue
s = sqrt(e) # (1)
r1 = (-b + s) / (2 * a)
r2 = (-b - s) / (2 * a)
ret += floor(r1) - ceil(r2) + 1
print(ret)
def main():
from math import floor, ceil, sqrt
fX, fY, fR = map(float, input().split())
X, Y, R = [round(x * 10000) for x in [fX, fY, fR]]
ret = 0
def isIn(x, y):
ret = (X - x * 10000) ** 2 + (Y - y * 10000) ** 2 <= R ** 2
return ret
for y in range(floor(fY - fR), ceil(fY + fR) + 1):
# find start
left = floor(fX - fR - 1) # (2)
init_right = right = floor(fX)
if isIn(right, y):
while left < right - 1:
x = (left + right) // 2
if isIn(x, y):
right = x
else:
left = x
ret += init_right - left
# find end
init_left = left = init_right + 1 # (3)
right = ceil(fX + fR + 1) # (4)
if isIn(left, y):
while left < right - 1:
x = (left + right) // 2
if isIn(x, y):
left = x
else:
right = x
ret += right - init_left
print(ret)