くろたんく雑記帳

日常とか、わんちゃんとか、機械学習とか、競プロとか、

MENU

Python3で解く AtCoder Beginner Contest 114 D - 756

階乗の約数のカウント、七五数のカウント。愚直に約数を列挙して数え上げるとだめで数え上げに組み合わせのを考えながら工夫が必要な、いい問題

目次

概要

問題

  • {\displaystyle n}が与えられる。
  • {\displaystyle n!}の約数の中に七五数は何個ある?
  • 七五数とは約数をちょうど75個持つ正の整数とする。

解くときに考えた内容

  • 約数のカウントは以下のように考える。

    • {\displaystyle [p, q, r]}素数とすると
    • {\displaystyle p^a \times q^b  \times r^c}の形でなにかの数字が表せるとすると、
    • {\displaystyle (a+1) \times (b+1) \times (c+1)}がその約数の数
  • {\displaystyle n!}の約数の中に七五数は何個あるで、約数を列挙して、それぞれの約数の数をカウントすると、TLEになってしまう。列挙せずに組み合わせのパターンで考える必要がある。

  • {\displaystyle n!}素数の数の数え上げを行う。

  • 七五数は{\displaystyle p^a \times q^b  \times r^c}でいうと、
  • {\displaystyle [a] = [74]}
    • {\displaystyle a \leq 74}となるような{\displaystyle p}の数
  • {\displaystyle [a, b] = [24, 2]}
    • {\displaystyle a \leq 24}となるような{\displaystyle p}の数 x ({\displaystyle b \leq 2} となるような{\displaystyle q}の数 {\displaystyle -1} )(以上になるなので、片側に含まれたらもう片側に含めたくないので)
  • {\displaystyle [a, b] = [14, 4]}
    • {\displaystyle a \leq 14}となるような{\displaystyle p}の数 x ({\displaystyle b \leq 4} となるような{\displaystyle q}の数 {\displaystyle -1} )
  • {\displaystyle [a, b, c] = [4, 4, 2]}
    • {\displaystyle a \leq 4}となるような{\displaystyle p}の数 x ({\displaystyle b \leq 4} となるような{\displaystyle q}の数 {\displaystyle -1}) x ({\displaystyle c \leq 2}となるような{\displaystyle 2}の数 {\displaystyle -2} ) を {\displaystyle 2} で割る
  • {\displaystyle q, r}{\displaystyle -1},{\displaystyle -2}するのは、ある数以上あるものとしているので、該当の素数たちのなかから一度選んだものを排除したい。
  • {\displaystyle [a, b, c] = [4, 4, 2]}の時2で割るのは、累乗が4以上になる素数が10個ある時に二つ選ぶ選び方なので

コード

# 階乗の素数のカウント用
def factorization_list(n):
    tmp = n
    i = 2
    while i*i <= n:
        if tmp%i == 0:
            cnt = 0
            # 割れる場合は割れなくなるまで同じ数でわる
            while tmp%i == 0:
                cnt += 1
                tmp //= i
            e[i] += cnt
        i += 1
    # 最後1になるか素数が余るので素数ならリストに追加
    if tmp != 1:
        e[tmp] += 1
    # nが1以外の素数だったら
    if e == [0] * (n+1):
        if n != 1:
            e[n] += 1
    return e
# m以上の個数(たとえばeの中に4以上のものがいくつあるかを調べる)    
def e_count(m):
    l = [i for i in e if i >= m]
    return (len(l))
n = int(input())
e = [0] * (n+1)
for i in range(2, n+1):
    factorization_list(i)
    # print(e)
# nが与えられた時に、1-indexでn!の素数の累乗の合計を示す。
# n=6
# 2! [0, 0, 1, 0, 0, 0, 0] 
# 3! [0, 0, 1, 1, 0, 0, 0]
# 4! [0, 0, 3, 1, 0, 0, 0]
# 5! [0, 0, 3, 1, 0, 1, 0]
# 6! [0, 0, 4, 2, 0, 1, 0]

# 重複しないようにうまくカウント、e_countはm以上だから一度選んだものを選ばないようにする
# 同じ値のものを選ぶときは選び方的に割り算する(mが4以上をを2つ選ぶ選び方のこと)
print(e_count(74) + \
    e_count(24) * (e_count(2)-1) + \
    e_count(14) * (e_count(4)-1) + \
    e_count(4)  * (e_count(4)-1) // 2 * (e_count(2)-2))def factorization_list(n):
    tmp = n
    i = 2
    while i*i <= n:
        if tmp%i == 0:
            cnt = 0
            # 割れる場合は割れなくなるまで同じ数でわる
            while tmp%i == 0:
                cnt += 1
                tmp //= i
            e[i] += cnt
        i += 1
    # 最後1になるか素数が余るので素数ならリストに追加
    if tmp != 1:
        e[tmp] += 1
    # nが1以外の素数だったら
    if e == [0] * (n+1):
        if n != 1:
            e[n] += 1
    return e
# m以上の個数(たとえばeの中に4以上のものがいくつあるかを調べる)    
def e_count(m):
    l = [i for i in e if i >= m]
    return (len(l))
n = int(input())
e = [0] * (n+1)
# nが与えられた時に、1-indexでn!の素数の累乗の合計を示す。
# n=6
# 2! [0, 0, 1, 0, 0, 0, 0] 
# 3! [0, 0, 1, 1, 0, 0, 0]
# 4! [0, 0, 3, 1, 0, 0, 0]
# 5! [0, 0, 3, 1, 0, 1, 0]
# 6! [0, 0, 4, 2, 0, 1, 0]
for i in range(2, n+1):
    factorization_list(i)
    print(e)
# 重複しないようにうまくカウント、e_countはm以上だから一度選んだものを選ばないようにする
# 同じ値のものを選ぶときは選び方的に割り算する(mが4以上をを2つ選ぶ選び方のこと)
print(e_count(74) + \
    e_count(24) * (e_count(2)-1) + \
    e_count(14) * (e_count(4)-1) + \
    e_count(4)  * (e_count(4)-1) // 2 * (e_count(2)-2))

参考になる書籍

けんちょんさんこと、大槻さんの書籍である、「問題解決力を鍛える!アルゴリズムとデータ構造」 ご本人の記事の中で難易度は、螺旋本ということで初学者でも非常に結構読みやすい!!!(実際に、けんちょんさんの記事はC++に疎い自分でも、その思考プロセスを学べるくらい丁寧に書かれているし、この書籍も非常に読みやすい)どのようなステータスの人にもおすすめの一冊になっている。

とうとう発売され自分の手元にも来た(2020-10-03)。現在読み中なのである程度読み込んだら感想を書く予定。めっちゃ図が多いし、章末問題もあるしかなりイケてる。答えはC++で書かれているがそのうちPythonでも書かれるとのことなので、自分で前もってやってしまおうと思う(答え合わせできるのはありがたい)。

7章までは別記事に残してある。 blacktanktop.hatenablog.com