問題
フィボナッチ数列 $F_0=0,\ F_1=1,\ F_{n+2}=F_{n+1}+F_n$ を $m$ で割った余りの数列 $F_0\bmod m,\ F_1\bmod m,\dots$ は周期的になる。最小の正の周期 $\pi(m)$($F_{\pi}\equiv0,\ F_{\pi+1}\equiv1\pmod m$ となる最小の正整数 $\pi$)を求めよ。
入力形式
m
制約
| # | 条件 |
|---|---|
| 1 | $1\le m\le10^{12}$($m=1$ のとき $\pi(1)=1$) |
入出力例
入力例1
10出力例1
60入力例2
1出力例2
1入力例3
1000000007出力例3
2000000016($10^9+7$ は素数で $\equiv\pm2\pmod5$ なので $\pi$ は $2(p+1)$ の約数。$2(p+1)=2000000016$ そのもの)
入力例4
1000000000000出力例4
1500000000000($\pi(10^k)=15\cdot10^{k-1}$ の形)
背景と出典
$\pi(p)$ について「$p\equiv\pm1\pmod5$ なら $p-1$ の約数、$p\equiv\pm2\pmod5$ なら $2(p+1)$ の約数、$\pi(2)=3,\ \pi(5)=20$」は標準的な結果と記憶している(本セッションでは原典を確認していない。Wall 1960 の論文が出典と記憶)。$\pi(p^e)=p^{e-1}\pi(p)$ は Wall–Sun–Sun 素数が存在しない限り成り立つ、とも記憶している。そのような素数は今まで見つかっていないと記憶しているが、探索範囲を含め本セッションでは確認していない。本問の制約($m\le10^{12}$)で確認した範囲は、下の検証ログのとおり。
この問題で確かめたいのは次の 3 点。(1) 素数冪と合成数を含む $m\le3000$ の全てで、反復の周期と一致すること。(2) $\pi(p^e)=\pi(p)$ と置く誤りが、いくつの $m$ で外れるか。(3) $m\approx10^{12}$ で、求めた値が本当に最小の周期になっていること($F_\pi\equiv0,F_{\pi+1}\equiv1$ かつ、$\pi$ を素因数で割ると成り立たない)。
ヒント(クリックで段階的に開示)
ヒント1(方向性)
$m=\prod p_i^{e_i}$ のとき、$\pi(m)=\mathrm{lcm}_i\ \pi(p_i^{e_i})$(各素数冪で周期になる最小の $n$ の最小公倍数)。まず素数 $p$ の $\pi(p)$ を考える。直接シミュレートすると $\pi(p)$ は最大 $2(p+1)$ 程度で、$p=10^{12}$ では間に合わない。
ヒント2(アプローチ)
$\pi(p)$ は、$p\equiv\pm1\pmod5$ なら $p-1$ の約数、そうでなければ $2(p+1)$ の約数($p=2,5$ は別扱い)。その数 $T$ から出発し、$T$ の素因数 $q$ ごとに「$T/q$ でも周期になるなら $T$ を $T/q$ に置き換える」を繰り返せば最小になる。周期になるかは $(F_T,F_{T+1})\equiv(0,1)$ で判定し、フィボナッチ数は倍加法で $O(\log T)$。
ヒント3(誘導)
素数冪は $\pi(p^e)=p^{e-1}\pi(p)$(Wall–Sun–Sun 素数でない限り)。$m\le10^{12}$ の素因数分解は $\sqrt m\le10^6$ までの試し割りで済む。$T$ は最大で約 $2\times10^{12}$ なので、$T$ の素因数分解には $\sqrt T\approx1.42\times10^6$ までの素数が要る(篩の上限を $1.5\times10^6$ にした理由)。
模範解答 (Python)
模範解答を表示する(まず自力で解いてから)
import sys
from math import gcd
def fibpair(k, m):
# (F_k, F_{k+1}) mod m を倍加法で
a, b = 0, 1
for bit in bin(k)[2:]:
c = a * ((2*b - a) % m) % m
d = (a*a + b*b) % m
if bit == '1': a, b = d, (c + d) % m
else: a, b = c, d
return a, b
def factor(x, primes):
f = {}
for p in primes:
if p*p > x: break
while x % p == 0:
f[p] = f.get(p, 0) + 1; x //= p
if x > 1: f[x] = f.get(x, 0) + 1
return f
def pisano_prime(p, primes):
if p == 2: return 3
if p == 5: return 20
T = p-1 if p % 5 in (1, 4) else 2*(p+1) # π(p) は T の約数
for q in factor(T, primes):
while T % q == 0 and fibpair(T//q, p) == (0, 1 % p):
T //= q
return T
def main():
m = int(sys.stdin.readline())
LIM = 1500000
sv = bytearray([1])*(LIM+1); sv[0] = sv[1] = 0
for i in range(2, int(LIM**0.5)+1):
if sv[i]: sv[i*i::i] = bytearray(len(sv[i*i::i]))
primes = [i for i in range(LIM+1) if sv[i]]
res = 1
for p, e in factor(m, primes).items():
pi = pisano_prime(p, primes) * p**(e-1) # π(p^e)=p^(e-1)π(p)(Wall–Sun–Sun 素数が無い前提)
res = res // gcd(res, pi) * pi
print(res)
main()
計算量: 篩 $O(L\log\log L)$($L=1.5\times10^6$)、各素因数について $T$ の素因数分解 $O(\pi(L))$ と倍加法 $O(\log T)$ を素因数の個数回。実測(Python 3.14、M1 Mac)で $m=10^{12}$ が 0.09 s(プロセス全体)。
Step-by-Step 解説
$m$ を割る互いに素な部分ごとに周期を求めて最小公倍数を取る(中国剰余定理)。$\pi(1)=1$。
$p\ne2,5$ のとき、$p\equiv\pm1\pmod5$ なら $\pi(p)\mid p-1$、そうでなければ $\pi(p)\mid2(p+1)$。$p=2$ は $0,1,1,0,1,1$ で 3、$p=5$ は 20。
候補 $T$ から出発し、$T$ の各素因数 $q$ について「$(F_{T/q},F_{T/q+1})\equiv(0,1)$ ならば $T\leftarrow T/q$」を、割れなくなるまで繰り返す。$T$ が周期なら $T$ の約数のうち周期になる最小のものが $\pi$ なので、素因数ごとに割れるだけ割れば最小になる。
$F_{2k}=F_k(2F_{k+1}-F_k)$、$F_{2k+1}=F_k^2+F_{k+1}^2$ を mod $p$ で使い、$(F_k,F_{k+1})$ を上位ビットから作る。$\log_2T\le41$ 回の繰り返し。
$\pi(p^e)=p^{e-1}\pi(p)$ とする。$m\le3000$ の全てで反復の周期と一致した。これはこの範囲に反例が無いことしか示さず、一般の保証にはならない。置き換えず $\pi(p^e)=\pi(p)$ とすると、$m\le3000$ のうち 546 個で外れた。
迷った他案と採らなかった理由
| 案 | 計算量 | 採否 | 理由 |
|---|---|---|---|
| 素数ごとの $T$ から約数を落とす+倍加法+素数冪の持ち上げ(本解) | $O(\sqrt m)$ の試し割り+素因数ごとに $O(\log m)$ | 採用 | $m\le3000$ の全件、$3001\ldots60000$ の 200 件で反復と一致 |
| $F_n\bmod m$ をそのまま反復 | $O(\pi(m))$、最大 $6m$ | 検算用のみ | $m\le6\times10^4$ でしか動かない |
| 行列 $\begin{pmatrix}1&1\\1&0\end{pmatrix}$ の位数を探索 | $O(\pi(m)\log)$ | 不採用 | 反復と同じ規模。周期の約数構造を使わない |
| $\pi(p^e)=\pi(p)$ のまま | $O(\sqrt m)$ | 不採用 | $m\le3000$ で 546 個外れる |
前提が変わったら:
- $m>10^{12}$(例えば $10^{18}$)では $\sqrt m=10^9$ の試し割りが重く、Pollard の rho 法などの素因数分解が要る。本問の制約を $10^{12}$ にした理由。実装していない
- Wall–Sun–Sun 素数が見つかると、その素数 $p$ で $\pi(p^2)=\pi(p)$ になり、本解の持ち上げが外れる。そのような素数は見つかっていない、と記憶している(未確認)
- 一般のフィボナッチ型数列($a_{n+2}=ba_{n+1}+ca_n$)や別の初項では、周期の候補の形($p\pm1$ の約数)が変わる。本解はそのままは使えない
よくあるミス
| ミス | 原因 | 正しい書き方 |
|---|---|---|
| $\pi(p^e)=\pi(p)$ と置く | 素数冪の周期は素数の周期の $p^{e-1}$ 倍になることを忘れる | pi * p**(e-1) |
| $p=5$ を $p-1$ か $2(p+1)$ の約数として扱う | $5\equiv0\pmod5$ はどちらの場合でもない | 20 を直接返す |
| $p=2$ の周期を 3 でなく 2 などにする | $0,1,1,0,1,1$ を確かめていない | 3 を直接返す |
| 篩の上限が $\sqrt T$ に届かない | $T\le2\times10^{12}$ で $\sqrt T\approx1.42\times10^6$ | 上限を $1.5\times10^6$ にして、最後の残りを素数と見なす |
次のステップ
- 発展1: $\pi(m)$ が $m$ の候補($m\le10^{12}$)のうち最大になる $m$ を探し、$6m$ との比を見る
- 発展2: $m>10^{12}$ に拡張するために Pollard の rho 法を足す
- 次回予告: 焦点帯 M1 から 3 問以上を含む通常のローテーション
検証ログ(本セッションで実行した数値)
- 反復との照合(実測): $1\le m\le3000$ の全 3000 件で、$(F_n,F_{n+1})\equiv(0,1)$ になる最小の $n$ を反復で求めた値と一致。$3001\le m\le60000$ のランダム 200 件も一致。素数冪($2,3,5,7,11,13,101,997$ の $e\le4$、$m\le3\times10^5$)も一致
- 誤った式(実測): $\pi(p^e)=\pi(p)$ と置くと、$m\le3000$ の 546 個で外れる
- 最小性の確認(実測): $5\times10^{11}\le p\le10^{12}$ の素数 60 個と、$10^{11}\le m\le10^{12}$ の 100 個について、求めた $\pi$ が $(F_\pi,F_{\pi+1})\equiv(0,1)$ を満たし、$\pi$ を素因数で割ると満たさないことを確認。ただし最小性の判定に使う素因数分解は本解と同じ関数なので、分解が不完全でも検出できない(篩の上限が $\sqrt T$ 以上であることは別途確認)
- 入力例(実測): 10 は 60、1 は 1、1000000007 は 2000000016、$10^{12}$ は 1500000000000(出力例どおり)
- 実行時間(実測): $m=10^{12}$ で 0.09 s(プロセス全体)
- 扱っていない範囲: Wall の定理と $\pi(p^e)=p^{e-1}\pi(p)$ の原典確認、Wall–Sun–Sun 素数の探索範囲の確認、$m>10^{12}$、一般の線形漸化式