AtCoder Beginner Contest 178をPythonで解く

投稿日:  更新日:2022/09/02

Atcoder Python

B!
Daniel AgreloによるPixabay(https://pixabay.com/)からの画像

こんにちは, Shinoryoです.

今回はAtCoder Beginner Contest 178を, Pythonで解いてみた結果を書き連ねていこうと思います.

A - Not

0なら1, 1なら0を出力すればいいので, すなわち入力値をxとすれば1xを出力すればよいことになります.

print(1-int(input()))

B - Product Max

最大になりうるのはa×c, a×d, b×c, b×dのどれかです. それらの中で最大の値を出力します.

a, b, c, d = [int(x) for x in input().split()]
print(max(a*c, a*d, b*c, b*d))

C - Ubiquity

  • 全ての整数列:10N通り
  • 0が存在しない整数列:9N通り
  • 9が存在しない整数列:9N通り
  • 09も存在しない整数列:8N通り

以上から, 求めるべき値は10N2×9N+8N109+7で割った剰余であることが分かります.

Python3の場合は, とりあえず律儀にそれを求めても問題はないと思います.

N = int(input())
print((10**N - 2*9**N + 8**N) % (10**9 + 7))

整数の値が必要以上に大きくならないように, 累乗の処理の中に109+7で割った剰余を求める処理を組み込むこともできます.

# 累乗したものをmodで除した剰余を求める関数を定義
def ruijo(a, k):
ans = 1
for _ in range(k):
ans *= a
# 掛け算を行うたびに剰余を求める処理を行う
ans %= mod
return ans
# 簡単のため, modに10**9 + 7を格納
mod = 10**9 + 7
# 入力
N = int(input())
# 出力
print((ruijo(10,N) - 2*ruijo(9,N) + ruijo(8,N)) % mod)

D - Redistribution

動的計画法(dynamic programming)で解くことを考えます. S=1に対する求める解答をA1, S=2に対する求める解答をA2, ……のように書きます. A1=0, A2=0, A3=1, A4=1, A5=1です. そして, S=6に対して, 問題文の条件に当てはまる整数列は, 以下のものになります.

  • その整数自身({6})
  • 3に対する整数列群(の右側)に6を加えたもの({3,3})

少し飛んで, S=9に対して, 問題文の条件に当てはまる整数列は, 以下のものになります.

  • その整数自身({9})
  • 6に対する整数列群(の右側)に3を加えたもの({6,3}, {3,3,3})
  • 5に対する整数列群(の右側)に4を加えたもの({5,4})
  • 4に対する整数列群(の右側)に5を加えたもの({4,5})
  • 3に対する整数列群(の右側)に6を加えたもの({3,6})

より一般的にS6に対して言えば, 以下のようになります.

  • その整数自身
  • S3に対する整数列群(の右側)に3を加えたもの
  • S4に対する整数列群(の右側)に4を加えたもの
  • ……
  • 3に対する整数列群(の右側)にS3を加えたもの

したがって, S6に対する漸化式として,

(1)An=An3+An4++A3+1

が成り立つことが分かります. ここで, A1=A2=0であることを利用し, またA0=1と定義する(上の箇条書きにおける「その整数自身」の代わり)と, 漸化式(1)

(2)An=An3+An4++A3+A2+A1+A0

のようになり, S3にまで拡張することができます.

また, 漸化式(2)の添え字を1ずらすことによって,

(3)An1=An4+An5++A3+A2+A1+A0

となります. (2), (3)より, 新たな漸化式

(4)An=An1+An3

を得ることができます.

どちらの漸化式を用いても解くことができます.

まずは, 漸化式(2)を用いた例.

def dp(n):
# 割る数を格納しておく
mod = 10**9 + 7
# Sが3以上かそうでないかで場合分け
if n > 2:
# 3以上であれば漸化式を用いる
dp = [0] * (n+1)
# 初期値
dp[0] = 1
dp[1] = 0
dp[2] = 0
# 漸化式の計算
for i in range(3, n+1):
for j in range(i - 2):
dp[i] += dp[j] % mod
# 出力
return dp[n] % mod
else:
# 2以下であれば0を出力
return 0
# 入力と出力
print(dp(int(input())))

そして, 漸化式(4)を用いた例.

def dp(n):
# 割る数を格納しておく
mod = 10**9 + 7
# Sが3以上かそうでないかで場合分け
if n > 2:
# 3以上であれば漸化式を用いる
dp = [0] * (n+1)
# 初期値
dp[0] = 1
dp[1] = 0
dp[2] = 0
# 漸化式の計算
for i in range(3, n+1):
dp[i] = (dp[i-1] + dp[i-3]) % mod
# 出力
return dp[n]
else:
# 2以下であれば0を出力
return 0
# 入力と出力
print(dp(int(input())))

E以降

E以降は私の能力不足故に省略いたします.

参考にしたサイト等

Search

About Me

自分の写真
理系大学生でした. Bloggerを利用して発信を行っています.

Labels

Blog Archives