188AC - ABC048C: Boxes and Candies
ABC048-C (300 points)
問題
それぞれ 個のキャンディが入った箱が 個並んでいる.
箱に入っているキャンディを食べて, どの隣り合う箱を見ても, それらの箱に入っているキャンディの個数の和が 以下になるようにするとき, 食べなければならない最小個数を求める.
方針
素直に端から順番に条件を満たすように食べていきましょう.
# input N, x = map(int, input().split()) a = list(map(int, input().split())) ans = 0 for i in range(N - 1): if a[i] > x: ans += a[i] - x a[i] = x if a[i] + a[i + 1] > x: ans += a[i] + a[i + 1] - x a[i + 1] -= a[i] + a[i + 1] - x print(ans)
183AC - ABC106D: AtCoder Express 2
ABC106-D (400 points)
方針
- 以下の記事に完全にお世話になりました.
http://hama-du-competitive.hatenablog.com/entry/2017/04/22/185540
- 想定解は二次元累積和.
# input N, M, Q = map(int, input().split()) train_query = {} # 対象区間とクエリを一緒にソート for i in range(M + Q): train_query[i] = list(map(int, input().split())) train_query = sorted(train_query.items(), key=lambda x: x[1][1]) print(train_query) # 辞書をソートするとリストが返ってくることに注意 StartPoints = [0 for _ in range(N)] # 対象区間の開始位置 ans = [0 for _ in range(Q)] # 各クエリに対する答え for j in range(M + Q): if train_query[j][0] < M: # 対象区間 StartPoints[train_query[j][1][0] - 1] += 1 else: # クエリ ans[train_query[j][0] - M] = sum(StartPoints[(train_query[j][1][0] - 1):(train_query[j][1][1])]) for i in range(Q): print(ans[i])
182AC - ABC106C: To Infinity
ABC106-C (300 points)
問題
~ の数字からなる文字列 が以下のように変化するとき, 兆日後の文字列の左から 番目の数を求める.
- 日たつと, 文字列 の は , は , , は に置き換わる.
- 兆日後の文字列の長さは 以上.
方針
- 兆日後には 以外の数字は 実質的に無限個並んでいる.
- の最初の 文字の中に, 以外の数字が含まれていれば, そのような数字の中で最初に出てくる数字
- そうでなければ
# input S = input() K = int(input()) for i in range(K): if int(S[i]) != 1: print(int(S[i])) exit() elif i == K - 1: print(int(S[i]))
177AC - ABC050C: Lining Up
ABC050-C (300 points)
問題
以下の条件を満たす 人の並び方の総数を で割った余りを出力する.
- 人 の右側に並んでいる人数と左側に並んでいる人数の差の絶対値は .
方針
- 人 の左に並んでいる人数を とすると, 右に並んでいる人数は となり, 全員で 人であることから
- 条件を満たす並び方がゼロになる場合:
- と偶奇が同じ が存在(このとき が整数にならない).
- に 同じ数が つ以上含まれる( は 通り).
- が奇数のとき, に が つ以上含まれる.
- これら以外の場合, となる 人 は左右を入れ替えることが可能なので, 並び方の総数は 通り.
# input N = int(input()) A = list(map(int, input().split())) cnt = [0 for i in range(N)] ans = 1 if N % 2 == 0: for i in range(N): if A[i] % 2 == 0: print(0) exit() cnt[A[i]] += 1 if cnt[A[i]] > 2: print(0) exit() if cnt[A[i]] == 1: ans = (ans * 2) % (10 ** 9 + 7) print(ans) else: for i in range(N): if A[i] % 2 == 1: print(0) exit() if A[i] > 0: cnt[A[i]] += 1 if cnt[A[i]] > 2: print(0) exit() if cnt[A[i]] == 1: ans = (ans * 2) % (10 ** 9 + 7) if A[i] == 0: cnt[0] += 1 if cnt[0] > 1: print(0) exit() print(ans)
174AC - ABC104C: All Green
ABC104-C (300 points)
問題
点の問題がそれぞれ 問, 計 問の問題が与えられ, 総合スコアを以下のように計算するとき, 点以上の総合スコアを獲得するために解かなければならない最少の問題数を求める.
- 基本スコア:解いた問題すべての配点の合計.
- コンプリートボーナス: 点を付けられた 問の問題すべてを解くと, 基本スコアとは別に 点を獲得.
- 総合スコア:基本スコアとコンプリートボーナスの合計.
- 入力は全て整数.
- は全て100の倍数.
- 総合スコアを 点以上にすることは可能.
方針
- なので, 各点数の問題群について全て解く or 解かないで ケースを全探索.
import math # input D, G = map(int, input().split()) Problems = [list(map(int, input().split())) for _ in range(D)] ans = float('inf') for i in range(1 << D): # bit全探索 solved = [a for a in range(D)] # 全て解く=ボーナス点をもらう問題群 count = 0 point = 0 for j in range(D): # 全て解く=ボーナス点をもらう問題群の点数合計 if i & (1 << j): # (j + 1) * 100 点の問題を全て解く場合 count += Problems[j][0] point += Problems[j][0] * (j + 1) * 100 + Problems[j][1] solved.remove(j) # (j + 1) * 100 点の問題は全て解答済 if point < G and len(solved) > 0: k = max(solved) if math.ceil((G - point) / ((k + 1) * 100)) > Problems[k][0] - 1: continue else: count += math.ceil((G - point) / ((k + 1) * 100)) ans = min(ans, count) else: ans = min(ans, count) print(ans)
171AC - ABC051C: Back and Forth
ABC51-C (300 points)
問題
点 間を, 途中で同じ座標を複数回通らないように 往復するとき, 最短経路を求める.
- 入力は全て整数.
方針
- 往復目は素直に行けば良い.
- 往復目は, 上下左右に だけ余分に移動すればOK.
# input sx, sy, tx, ty = map(int, input().split()) for i in range(ty - sy): print('U', end = "") for i in range(tx - sx): print('R', end = "") for i in range(ty - sy): print('D', end = "") for i in range(tx - sx): print('L', end = "") print('L', end = "") for i in range(ty - sy + 1): print('U', end = "") for i in range(tx - sx + 1): print('R', end = "") print('D', end = "") print('R', end = "") for i in range(ty - sy + 1): print('D', end = "") for i in range(tx - sx + 1): print('L', end = "")
165AC - ABC052C: Factors of Factorial
ABC052-C (300 points)
問題
整数 が与えられるとき, の正の約数の個数を で割った余りを求める.
方針
であるとき, 約数の個数 は
- modの計算は掛け算の途中でしても良いので, 各素因数についてmodを取りながら約数を数えていく.
参考
sucrose.hatenablog.com
qiita.com
import math # input N = int(input()) def prime_factor_table(n): table = [0] * (n + 1) for i in range(2, n + 1): if table[i] == 0: for j in range(i + i, n + 1, i): table[j] = i return table def prime_factor(n, prime_factor_table): prime_count = dict() while prime_factor_table[n] != 0: if prime_factor_table[n] in prime_count.keys(): prime_count[prime_factor_table[n]] += 1 else: prime_count[prime_factor_table[n]] = 1 n = int(n/prime_factor_table[n]) if n in prime_count.keys(): prime_count[n] += 1 else: prime_count[n] = 1 return prime_count Ps = dict() P_1000 = prime_factor_table(1000) ans = 1 for i in range(2, N + 1): P_i = prime_factor(i, P_1000) for k in P_i.keys(): if k in Ps.keys(): Ps[k] += P_i[k] else: Ps[k] = P_i[k] for k in Ps.keys(): ans = (ans * (Ps[k] + 1)) % (10 ** 9 + 7) print(ans)