2020-10-31
【Python】ARC107 解説
ARC107に参加しました. 結果はABC3完1312位パフォーマンス1259. 不本意な結果..
以下, A~D問題の解説およびPython解答例です.
A - Simple Math
公式解説の通り. わざわざ逆元を求めて計算したけど, この程度の大きさであれば直接2で割ってもよいのか…
A, B, C = map(int, input().split())
MOD = 998244353
inv2 = pow(2, MOD - 2, MOD)
X = (1 + A) * A * inv2
Y = (1 + B) * B * inv2
Z = (1 + C) * C * inv2
ans = (X * Y * Z) % MOD
print(ans)
B - Quadruple
めちゃくちゃ手こずった. 公式解説みたいにをスマートに導出できる人なんているんだろうか…
私の考え方は以下の通り.
- まず, , とおくと, 条件は, , となる.
- ここで①より, が決まればも決まるため, 各について, 答えを数え上げていけば良い.
- では, を満たす整数の組はいくつ存在するか?
- まず, が満たすべき条件は である.
- 同様にして, が満たすべき条件は . つまり,
- 結局, の範囲に含まれる整数の数が, の組の個数となる.
- を満たす整数の組についても同様に求めることができる.
N, K = map(int, input().split())
cnt = 0
for X in range(2, 2 * N + 1):
l = max(1, X - N) # max(1, max(1, X - N))
r = min(X - 1, N) # min(min(X - 1, N), X - 1)
a = max(0, r - l + 1)
Y = X - K
l = max(1, Y - N)
r = min(Y - 1, N)
b = max(0, r - l + 1)
cnt += a * b
print(cnt)
C - Shuffle Permutation
比較的わかりやすい問題だと感じた.
公式解説のとおり, スワップ可能な行・列をそれぞれUnionFindによりグループ分けして, 各グループ内での並べ替え方をすべて掛け合わせる.
def prepare(n):
# 割愛
# modFacts[i]:= i! % MOD
# invs[i]:= pow(i!, MOD - 2, MOD)
# return modFacts, invs
class UnionFind():
# 割愛
# union(i, j): ノードi, jをグループ化
# parents[i]: i>=0のとき親ノード番号, i<0のとき自身が親のグループのノード個数.
N, K = map(int, input().split())
A = [list(map(int, input().split())) for _ in range(N)]
MOD = 998244353
modFacts, invs = prepare(N)
ufH = UnionFind(N) # ufH: 列に関するUnionFind木
for i in range(N - 1):
for j in range(i + 1, N):
if all(A[i][k] + A[j][k] <= K for k in range(N)):
ufH.union(i, j)
ufW = UnionFind(N) # ufW: 行に関するUnionFind木
for i in range(N - 1):
for j in range(i + 1, N):
if all(A[k][i] + A[k][j] <= K for k in range(N)):
ufW.union(i, j)
varH = 1 # varH: 列の並べ替え方の個数
for v in ufH.parents:
if v < 0:
varH *= modFacts[-v]
varH %= MOD
varW = 1 # varW: 列の並べ替え方の個数
for v in ufW.parents:
if v < 0:
varW *= modFacts[-v]
varW %= MOD
print((varH * varW) % MOD)
D - Number of Multisets
解説AC.
考え方としては分割数の典型.
MOD = 998244353
N, K = map(int, input().split())
dp = [0] * (N + 2) # dp配列を使い回す. dp[N + 1]は番兵.
dp[0] = 1
for i in range(1, N + 1):
for k in range(N, -1, -1):
# dp[k] = dp[k - 1] + dp[2 * k]
dp[k] = dp[k - 1]
if 2 * k <= N:
dp[k] += dp[2 * k]
dp[k] %= MOD
print(dp[K])
E - Mex Mat
TBA
F - Sum of Abs
TBA
関連記事最新記事
2020-10-11【Python】ARC105 解説
2021-05-09【Python】AtCoder - 30代社会人が始めて1年半で青色になりました
2021-04-12【Python】ABC198 解説
2021-03-27【Python】ABC197 解説
2021-03-20【Python】ABC196 解説