Open34

蟻本

アガサ・アイスティアガサ・アイスティ

P8 くじびき

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

S = set(i + j for i in K for j in K)
f = any(M - s in S for s in S)

print("Yes" if f else "No")

アガサ・アイスティアガサ・アイスティ

P21 三角形

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

A.sort()

ans = 0
for i in range(N - 2):
    if A[i] + A[i + 1] > A[i + 2]:
        ans = max(ans, sum(A[i : i + 3]))

print(ans)

アガサ・アイスティアガサ・アイスティ

P23 Ants (POJ No.1852)

N, L = map(int, input().split())
X = list(map(int, input().split()))

t_min = max(min(x, L - x) for x in X)
t_max = max(max(x, L - x) for x in X)

print(t_min, t_max)

アガサ・アイスティアガサ・アイスティ

P34 部分和問題

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

f = False
for bit in range(1 << N):
    sum = 0
    for i in range(N):
        if bit & 1 << i:
            sum += A[i]

    if sum == K:
        f = True

print("Yes" if f else "No")

アガサ・アイスティアガサ・アイスティ

P35 Lake Counting

import sys
sys.setrecursionlimit(10 ** 6)


def dfs(x, y):
    G[x][y] = "."
    for dx in [-1, 0, 1]:
        for dy in [-1, 0, 1]:
            nx, ny = x + dx, y + dy
            if G[nx][ny] == "W":
                dfs(nx, ny)


N, M = map(int, input().split())
G = [list(input()) for _ in range(N)]

for g in G:
    g.append(".")
G.append(["."] * (M + 1))

ans = 0
for i in range(N):
    for j in range(M):
        if G[i][j] == "W":
            dfs(i, j)
            ans += 1

print(ans)

アガサ・アイスティアガサ・アイスティ

P37 迷路の最短路

from collections import deque


N, M = map(int, input().split())
G = [list(input()) for _ in range(N)]

for g in G:
    g.append("#")
G.append(["#"] * (M + 1))

INF = 1 << 60
d = [[INF] * M for _ in range(N)]
q = deque()
for i in range(N):
    for j in range(M):
        if G[i][j] == "S":
            d[i][j] = 0
            q.append((i, j))

while q:
    x, y = q.popleft()

    if G[x][y] == "G":
        print(d[x][y])
        break

    for dx, dy in [(1, 0), (0, 1), (-1, 0), (0, -1)]:
        nx, ny = x + dx, y + dy
        if G[nx][ny] != "#" and d[nx][ny] == INF:
            d[nx][ny] = d[x][y] + 1
            q.append((nx, ny))

アガサ・アイスティアガサ・アイスティ

P42 硬貨の問題

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

V = [1, 5, 10, 50, 100, 500]

ans = 0
for i in reversed(range(6)):
    t = min(A // V[i], C[i])
    A -= t * V[i]
    ans += t

print(ans)

アガサ・アイスティアガサ・アイスティ

P43 区間スケジューリング問題

N = int(input())
ST = [tuple(map(int, input().split())) for _ in range(N)]

ST.sort(key=lambda x: x[1])

last = 0
ans = 0
for s, t in ST:
    if last < s:
        last = t
        ans += 1

print(ans)

アガサ・アイスティアガサ・アイスティ

P45 Best Cow Line (POJ 3617)

N = int(input())
S = input()

l = 0
r = N - 1
ans = ""
while l <= r:
    if S[l : r + 1] < S[l : r + 1][::-1]:
        ans += S[l]
        l += 1
    else:
        ans += S[r]
        r -= 1

print(ans)

アガサ・アイスティアガサ・アイスティ

P47 Saruman's Army (POJ 3069)

from bisect import bisect_right


N, R = map(int, input().split())
X = list(map(int, input().split()))

X.sort()

i = 0
ans = 0
while i < N:
    i = bisect_right(X, X[i] + R) - 1
    ans += 1
    i = bisect_right(X, X[i] + R)

print(ans)

アガサ・アイスティアガサ・アイスティ

P49 Fence Repair (POJ 3253)

import heapq


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

heapq.heapify(L)

ans = 0
while len(L) >= 2:
    l1 = heapq.heappop(L)
    l2 = heapq.heappop(L)
    ans += l1 + l2
    heapq.heappush(L, l1 + l2)

print(ans)

アガサ・アイスティアガサ・アイスティ

P52 01 ナップサック問題

import numpy as np


N, W = map(int, input().split())
WV = [tuple(map(int, input().split())) for _ in range(N)]

dp = np.zeros(W + 1, np.int64)
for w, v in WV:
    dp[w:] = np.maximum(dp[w:], dp[:-w] + v)

print(dp[W])

アガサ・アイスティアガサ・アイスティ

P56 最長共通部分列問題

import numpy as np


N, M = map(int, input().split())
S = np.array(list(input()))
T = np.array(list(input()))

equal = S[:, None] == T[None, :]

dp = np.zeros(M + 1, np.int64)
for i in range(N):
    dp[1:] = np.maximum(dp[1:], dp[:-1] + equal[i])
    dp = np.maximum.accumulate(dp)

print(dp[M])

アガサ・アイスティアガサ・アイスティ

P58 個数制限なしナップサック問題

N, W = map(int, input().split())
WV = [tuple(map(int, input().split())) for _ in range(N)]

dp = [0] * (W + 1)
for w, v in WV:
    for i in range(w, W + 1):
        dp[i] = max(dp[i], dp[i - w] + v)

print(dp[W])

アガサ・アイスティアガサ・アイスティ

P60 01 ナップサック問題その2

import numpy as np


N, W = map(int, input().split())
WV = [tuple(map(int, input().split())) for _ in range(N)]

MAX_V = 100
INF = 1 << 60
dp = np.full(MAX_V * N + 1, INF, np.int64)
dp[0] = 0
for w, v in WV:
    dp[v:] = np.minimum(dp[v:], dp[:-v] + w)

ans = np.where(dp <= W)[0][-1]
print(ans)

アガサ・アイスティアガサ・アイスティ

P62 個数制限付き部分和問題

import numpy as np


N, K = map(int, input().split())
AM = [tuple(map(int, input().split())) for _ in range(N)]

dp = np.full(K + 1, -1, np.int64)
dp[0] = 0
for a, m in AM:
    dp = np.where(dp >= 0, m, -1)
    for i in range(a, K + 1):
        dp[i] = max(dp[i], dp[i - a] - 1)

print("Yes" if dp[K] >= 0 else "No")

アガサ・アイスティアガサ・アイスティ

P63 最長増加部分列問題

from bisect import bisect_left


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

INF = 1 << 60
dp = [INF] * N
for a in A:
    dp[bisect_left(dp, a)] = a

ans = bisect_left(dp, INF)
print(ans)

アガサ・アイスティアガサ・アイスティ

P66 分割数

N, M, MOD = map(int, input().split())

dp = [0] * (N + 1)
dp[0] = 1
for i in range(1, M + 1):
    for j in range(i, N + 1):
        dp[j] = (dp[j] + dp[j - i]) % MOD

print(dp[N])

アガサ・アイスティアガサ・アイスティ

P67 重複組み合わせ

import numpy as np


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

dp = np.zeros(M + 1, np.int64)
dp[0] = 1
for a in A:
    dp[a + 1 :] -= dp[: -(a + 1)]
    dp = np.cumsum(dp) % MOD

print(dp[M])

アガサ・アイスティアガサ・アイスティ

P73 Expedition (POJ 2431)

import heapq


N, L, P = map(int, input().split())
AB = [tuple(map(int, input().split())) for _ in range(N)]

AB.append((L, 0))
que = []
pos = 0
ans = 0
for a, b in AB:
    P -= a - pos
    while P < 0:
        if not que:
            print(-1)
            exit()
        P += -heapq.heappop(que)
        ans += 1

    heapq.heappush(que, -b)
    pos = a

print(ans)

アガサ・アイスティアガサ・アイスティ

P85 食物連鎖 (POJ 1182)

DSU
import sys
sys.setrecursionlimit(10 ** 6)


class DSU:
    def __init__(self, n):
        self._n = n
        self.parent_or_size = [-1] * n

    def merge(self, a, b):
        assert 0 <= a < self._n
        assert 0 <= b < self._n
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return x
        if -self.parent_or_size[x] < -self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x

    def same(self, a, b):
        assert 0 <= a < self._n
        assert 0 <= b < self._n
        return self.leader(a) == self.leader(b)

    def leader(self, a):
        assert 0 <= a < self._n
        if self.parent_or_size[a] < 0:
            return a
        self.parent_or_size[a] = self.leader(self.parent_or_size[a])
        return self.parent_or_size[a]

    def size(self, a):
        assert 0 <= a < self._n
        return -self.parent_or_size[self.leader(a)]

    def groups(self):
        leader_buf = [self.leader(i) for i in range(self._n)]
        result = [[] for _ in range(self._n)]
        for i in range(self._n):
            result[leader_buf[i]].append(i)
        return [r for r in result if r != []]

# ここにDSUのコードを貼り付ける


N, K = map(int, input().split())
TXY = [tuple(map(int, input().split())) for _ in range(K)]

dsu = DSU(N * 3 + 1)
ans = 0
for (t, x, y) in TXY:
    if not (1 <= x <= N and 1 <= y <= N):
        ans += 1
        continue

    if t == 1:
        if dsu.same(x, y + N) or dsu.same(x, y + N * 2):
            ans += 1
        else:
            dsu.merge(x, y)
            dsu.merge(x + N, y + N)
            dsu.merge(x + N * 2, y + N * 2)
    else:
        if dsu.same(x, y) or dsu.same(x, y + N * 2):
            ans += 1
        else:
            dsu.merge(x, y + N)
            dsu.merge(x + N, y + N * 2)
            dsu.merge(x + N * 2, y)

print(ans)

アガサ・アイスティアガサ・アイスティ

P93 二部グラフ判定

DSU
import sys
sys.setrecursionlimit(10 ** 6)


class DSU:
    def __init__(self, n):
        self._n = n
        self.parent_or_size = [-1] * n

    def merge(self, a, b):
        assert 0 <= a < self._n
        assert 0 <= b < self._n
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return x
        if -self.parent_or_size[x] < -self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x

    def same(self, a, b):
        assert 0 <= a < self._n
        assert 0 <= b < self._n
        return self.leader(a) == self.leader(b)

    def leader(self, a):
        assert 0 <= a < self._n
        if self.parent_or_size[a] < 0:
            return a
        self.parent_or_size[a] = self.leader(self.parent_or_size[a])
        return self.parent_or_size[a]

    def size(self, a):
        assert 0 <= a < self._n
        return -self.parent_or_size[self.leader(a)]

    def groups(self):
        leader_buf = [self.leader(i) for i in range(self._n)]
        result = [[] for _ in range(self._n)]
        for i in range(self._n):
            result[leader_buf[i]].append(i)
        return [r for r in result if r != []]

# ここにDSUのコードを貼り付ける


N, M = map(int, input().split())
AB = [tuple(map(int, input().split())) for _ in range(M)]

dsu = DSU(N * 2)
for a, b in AB:
    if dsu.same(a, b) or dsu.same(a + N, b + N):
        print("No")
        exit()

    dsu.merge(a, b + N)
    dsu.merge(a + N, b)

print("Yes")

アガサ・アイスティアガサ・アイスティ

P102 Roadblocks (POJ No.3255)

import heapq


N, R = map(int, input().split())
ABC = [tuple(map(int, input().split())) for _ in range(R)]

G = [[] for _ in range(N)]
for a, b, cost in ABC:
    a -= 1
    b -= 1
    G[a].append((b, cost))
    G[b].append((a, cost))

INF = 1 << 60
d1 = [INF] * N
d2 = [INF] * N
d1[0] = 0
que = [(0, 0)]

while que:
    d, v = heapq.heappop(que)
    if d > d2[v]:
        continue
    for to, cost in G[v]:
        if d + cost < d1[to]:
            d1[to] = d + cost
            heapq.heappush(que, (d1[to], to))

        if d1[to] < d + cost < d2[to]:
            d2[to] = d + cost
            heapq.heappush(que, (d2[to], to))

print(d2[N - 1])

アガサ・アイスティアガサ・アイスティ

P103 Conscription (POJ No.3723)

DSU
import sys
sys.setrecursionlimit(10 ** 6)


class DSU:
    def __init__(self, n):
        self._n = n
        self.parent_or_size = [-1] * n

    def merge(self, a, b):
        assert 0 <= a < self._n
        assert 0 <= b < self._n
        x, y = self.leader(a), self.leader(b)
        if x == y:
            return x
        if -self.parent_or_size[x] < -self.parent_or_size[y]:
            x, y = y, x
        self.parent_or_size[x] += self.parent_or_size[y]
        self.parent_or_size[y] = x
        return x

    def same(self, a, b):
        assert 0 <= a < self._n
        assert 0 <= b < self._n
        return self.leader(a) == self.leader(b)

    def leader(self, a):
        assert 0 <= a < self._n
        if self.parent_or_size[a] < 0:
            return a
        self.parent_or_size[a] = self.leader(self.parent_or_size[a])
        return self.parent_or_size[a]

    def size(self, a):
        assert 0 <= a < self._n
        return -self.parent_or_size[self.leader(a)]

    def groups(self):
        leader_buf = [self.leader(i) for i in range(self._n)]
        result = [[] for _ in range(self._n)]
        for i in range(self._n):
            result[leader_buf[i]].append(i)
        return [r for r in result if r != []]

# ここにDSUのコードを貼り付ける


N, M, R = map(int, input().split())
XYD = [tuple(map(int, input().split())) for _ in range(R)]

XYD.sort(key=lambda x: -x[2])
dsu = DSU(N + M)
ans = 10000 * (N + M)
for x, y, d in XYD:
    if not dsu.same(x, y + N):
        dsu.merge(x, y + N)
        ans -= d

print(ans)

アガサ・アイスティアガサ・アイスティ

P104 Layout (POJ No.3169)

N, ML, MD = map(int, input().split())
ABD_L = [tuple(map(int, input().split())) for _ in range(ML)]
ABD_D = [tuple(map(int, input().split())) for _ in range(MD)]

edges = []
for i in range(N - 1):
    edges.append((i + 1, i, 0))

for al, bl, dl in ABD_L:
    al -= 1
    bl -= 1
    edges.append((al, bl, dl))

for ad, bd, dd in ABD_D:
    ad -= 1
    bd -= 1
    edges.append((bd, ad, -dd))

INF = 1 << 60
dist = [INF] * N
dist[0] = 0
updated = False
for i in range(N):
    for v, u, cost in edges:
        if dist[v] != INF and dist[u] > dist[v] + cost:
            dist[u] = dist[v] + cost
            if i == N - 1:
                updated = True

if updated:
    print(-1)
elif dist[N - 1] == INF:
    print(-2)
else:
    print(dist[N - 1])

アガサ・アイスティアガサ・アイスティ

P107 線分上の格子点の個数

from math import gcd


P1 = tuple(map(int, input().split()))
P2 = tuple(map(int, input().split()))

ans = gcd(P1[0] - P2[0], P1[1] - P2[1]) - 1
print(ans)

アガサ・アイスティアガサ・アイスティ

P108 双六

def extgcd(a, b):
    if not b:
        return a, 1, 0
    gcd, x, y = extgcd(b, a % b)
    return gcd, y, x - a // b * y


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

gcd, x, y = extgcd(A, B)
ans = [max(x, 0), max(-x, 0), max(y, 0), max(-y, 0)]
if gcd == 1:
    print(*ans)
else:
    print(-1)

アガサ・アイスティアガサ・アイスティ

P110 素数判定

N = int(input())

f = True
i = 2
while i * i <= N:
    if N % i == 0:
        f = False
    i += 1

print("Yes" if f else "No")

アガサ・アイスティアガサ・アイスティ

P111 素数の個数

import numpy as np


N = int(input())

is_prime = np.full(N + 1, True)
is_prime[0] = is_prime[1] = False
i = 2
while i * i <= N:
    if is_prime[i]:
        is_prime[i + i :: i] = False
    i += 1

print(np.sum(is_prime))

アガサ・アイスティアガサ・アイスティ

P113 区間内の素数の個数

import numpy as np


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

MAX_SQRT_B = 10 ** 6
is_prime = np.full(MAX_SQRT_B + 1, True)
is_prime[0] = is_prime[1] = False
is_prime2 = np.full(B - A, True)
i = 2
while i * i <= B:
    if is_prime[i]:
        is_prime[i + i :: i] = False
        is_prime2[-(-A // i) * i - A : B - A : i] = False
    i += 1

print(np.sum(is_prime2))

アガサ・アイスティアガサ・アイスティ

P114 Carmichael Numbers (UVa No.10006)

N = int(input())

f = False
i = 2
while i * i <= N:
    if N % i == 0:
        f = True
    i += 1

for x in range(1, N):
    if pow(x, N, N) != x:
        f = False

print("Yes" if f else "No")

アガサ・アイスティアガサ・アイスティ

P117 Minimum Scalar Product (2008 Round 1A A)

N = int(input())
V1 = list(map(int, input().split()))
V2 = list(map(int, input().split()))

V1.sort()
V2.sort(reverse=True)

ans = 0
for v1, v2 in zip(V1, V2):
    ans += v1 * v2

print(ans)

アガサ・アイスティアガサ・アイスティ

P119 Crazy Rows (2009 Round2 A)

import numpy as np


N = int(input())
M = [input() for _ in range(N)]

A = np.array([m.rfind("1") for m in M])

ans = 0
for i in range(N):
    pos = np.where(A[i:] <= i)[0][0] + i
    while pos > i:
        A[pos], A[pos - 1] = A[pos - 1], A[pos]
        pos -= 1
        ans += 1

print(ans)

アガサ・アイスティアガサ・アイスティ

P121 Bribe the Prisoners (2009 Round 1C C)

from functools import lru_cache


@lru_cache
def dfs(res, A):
    if len(A) == 2:
        return A[1] - A[0] - 1, ()

    cost = INF
    for i in range(1, len(A) - 1):
        cost_l = dfs(A[i] - A[0] - 1, A[: i + 1])[0]
        cost_r = dfs(A[-1] - A[i] - 1, A[i:])[0]
        cost = min(cost, cost_l + cost_r)
    return res + cost, ()


P, Q = map(int, input().split())
A = tuple(map(int, input().split()))

A = (0,) + A + (P + 1,)
INF = 1 << 60
print(dfs(0, A)[0])