結果

問題 No.8038 フィボナッチ数列の周期
コンテスト
ユーザー wasd314
提出日時 2026-10-23 13:55:15
言語 PyPy3
(8.0.0 + ACL)
コンパイル:
pypy3 -mpy_compile _filename_
実行:
pypy3 _filename_
結果
MLE  
実行時間 -
コード長 3,377 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 395 ms
コンパイル使用メモリ 64,632 KB
実行使用メモリ 779,384 KB
最終ジャッジ日時 2026-10-23 13:56:25
合計ジャッジ時間 57,239 ms
ジャッジサーバーID
(参考情報)
judge5_0 / judge2_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other MLE * 25
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

def sieves(nn: int):
    is_prime = [True] * nn
    least_p = [-1] * nn
    is_prime[0] = is_prime[1] = False
    least_p[1] = 1
    mobius = [1] * nn
    mobius[0] = 0
    for p in range(2, nn):
        if not is_prime[p]:
            continue
        least_p[p] = p
        mobius[p] = -1
        for q in range(p * 2, nn, p):
            is_prime[q] = False
            if least_p[q] == -1:
                least_p[q] = p
            if q % (p * p) == 0:
                mobius[q] = 0
            else:
                mobius[q] *= -1
    primes = [p for p in range(2, nn) if is_prime[p]]
    return is_prime, least_p, primes, mobius


def prime_factorize(n: int):
    ans = {}
    while n > 1:
        p = least_p[n]
        e = 0
        while n % p == 0:
            n //= p
            e += 1
        ans[p] = e
    return ans


def get_divisors(n: int):
    """正の約数列挙

    Args:
        n (int): 約数を求める数 (>= 1)

    Returns:
        list[int]: `n`の正の約数

    Notes:
        - `n`の約数の個数をσ(n)として
        - 計算量 Θ( σ(n) * log(σ(n)) )
        - n <= 10^7 で σ(n) <= σ(8648640) = 448
        - n <= 10^9 で σ(n) <= σ(735134400) = 1344
        - n <= 10^18 で σ(n) <= σ(897612484786617600) = 103680
    """
    pe = prime_factorize(n)
    ans = [1]
    for p, e in pe.items():
        exps = [p**ei for ei in range(1, e + 1)]
        ans.extend([d * f for d in ans for f in exps])
    ans.sort()
    return ans


is_prime, least_p, primes, mobius = sieves(2 * 10**7 + 100)


am = [[0, 1], [1, 1]]
e2 = [[1, 0], [0, 1]]


def mat_prod(m1, m2, mod):
    m2t = tuple(zip(*m2))
    return [
        [sum(m1ik * m2kj for m1ik, m2kj in zip(m1i, m2_j)) % mod for m2_j in m2t]
        for m1i in m1
    ]


def mat_pow(m, p, mod):
    if p == 1:
        return m
    mp = mat_pow(m, p // 2, mod)
    mp = mat_prod(mp, mp, mod)
    if p % 2:
        mp = mat_prod(mp, m, mod)
    return mp


def mat_pow_vec(m, p, v, mod):
    if p == 0:
        return v
    mp = mat_pow(m, p, mod)
    return [sum(mpij * vj for mpij, vj in zip(mpi, v)) % mod for mpi in mp]


def fib(n, mod):
    nv = mat_pow_vec(am, n, [0, 1], mod)
    return nv[0]


def test_shrink(pe, m):
    ans = 1
    for p, e in pe.items():
        ans *= p**e
    for p, e in pe.items():
        for _ in range(e):
            if mat_pow(am, ans // p, m) == e2:
                ans //= p
            else:
                break
    return prime_factorize(ans)


def period_p(p):
    ans = 0
    if p == 2:
        ans = 3
    elif p == 5:
        ans = 20
    elif pow(5, (p - 1) // 2, p) == 1:
        ans = p - 1
    else:
        ans = 2 * (p + 1)
    ans = test_shrink(prime_factorize(ans), p)
    return ans


def period_pp(p, e):
    p1 = period_p(p)
    if e == 1:
        return p1
    # *= p**(e-1)
    p1[p] = p1.get(p, 0) + e - 1
    return p1


def period(pe):
    # pisano period of Fib mod m
    if not pe:
        return {}
    ans = {}
    for p, e in pe.items():
        ansi = period_pp(p, e)
        for p_, e_ in ansi.items():
            ans[p_] = max(ans.get(p_, 0), e_)
    return ans


mod = 1_000_000_007

n = int(input())
pe = {}
for _ in range(n):
    p, e = map(lambda s_: int(s_), input().split())
    pe[p] = e
ans_pe = period(pe)
ans = 1
for p, e in ans_pe.items():
    ans *= pow(p, e, mod)
    ans %= mod
print(ans)
0