D苦手…WAが解決しない… 飛ばしてEはダイクストラでさっと解いて、残り30分 DをやるかFをやるかでFを考察する方が学びがありそうと判断し「いくつかの数のgcdであってmin以下のものの数」でサンプルは通ったがやっぱりTLE。この時点で残り13分なので残りはDをしてたけど最後まで解決せず4問
あー、そうか。Dは「10000倍して整数で扱おう…って二次関数の解を求めるところで平方根が出てくるじゃん…」となってたけど、そこを二分探索で求めるのか。数学的にはO(1)で解けるのでそれに無意識にこだわってしまったが、O(logR)でも間に合う、と。
Fは「いくつかの数のgcdであってmin以下のものの数」だと看破したのは正解であった。 それを効率よく求める方法が思いつけるとよかった。
水色に落ちるかなと思ったが、意外と+3だった
なるほど、DとFがかなり難易度高いのか。
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))
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()))
# (2)edges[i][j]で持ってるので多重辺を持つの面倒だったからdist) # (3)edges[i][i]とdist[i][j] + dist[j][i]$(i \neq j)$の中で最小のものを見つければ良い# (1)についてdefaultdict(dict)で扱ってる# (4)でアクセスする時に値が存在するかどうかチェックするのめんどいなと思った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)
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)
- 前者がダメで後者ならOKなの、自明ではない気がする
- gcd
- 前者$\sum_i \sum_x [x < \min(A)][x \text{ divides } A_i]$
- 後者$\sum_i \sum_x [x \text{ divides } A_i]$
- 前者の方が小さいよな…
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)
# (1)の平方根の計算が厄介# (2) これは確実に円の外である必要がある。 # (4)も同じfloor(fX - fR)だとちょうどピッタリ円周上になるケースがある# (3) 円の中心がちょうど整数である場合に、その頂点がダブルカウントされてしまわないように注意が必要
pythondef 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)