砂場で遊ぼう

c++/python/mathematica などの練習帳

Project Euler 001 / 3か5の倍数(Multiples of 3 or 5)

問題概略

1000 未満の自然数で,3 か 5 の倍数であるものの和を求めよ。

https://projecteuler.net/problem=1

for ループ

愚直に for ループをまわして条件をみたすものの和を計算します。

  ans = 0
  for i in range(1, 1000):
    if i % 3 == 0 or i % 5 == 0:
        ans += i
  print(ans)

内包表記

python らしく内包表記で書いてみました。条件をみたすものを抽出したリストを作ってその和を求めます。

  lst = [i for i in range(1000) if i % 3 == 0 or i % 5 == 0]
  print(sum(lst))

関数を定義

1000 未満の 3 の倍数は  \lfloor \frac{999}{3}\rfloor=333 個あって,その和は次のようになります。

 3\cdot 1+3\cdot 2+\cdots +3\cdot 333=3(1+2+\cdots+333)

これを一般化します。1000 未満の  n の倍数は  \lfloor \frac{999}{n}\rfloor 個あって,その和は次のようになります。

 f(n)=n\sum_{k=1}^{\lfloor \frac{999}{n}\rfloor} k=n\cdot \frac{1}{2} \left\lfloor \frac{999}{n}\right\rfloor \left(\left\lfloor \frac{999}{n}\right\rfloor+1\right)

求める和は  f(3)+f(5)-f(15) です。

  def f(n: int, mx: int) -> int:
    t = mx // n
    return n * t * (t + 1) // 2

  def solve(n: int) -> int:
    return f(3, n) + f(5, n) - f(15, n)

  if __name__ == "__main__":
    nmx = 1000
    print(solve(nmx - 1))