問題
正整数 $n$ と $Q$ 個の整数 $a_1,\dots,a_Q$ が与えられる。次を出力せよ。
- 1 行目: $\lambda(n)$。$n$ と互いに素な全ての $a$ について $a^k\equiv1\pmod n$ となる最小の正整数 $k$($n=1$ のとき 1)。
- 続く $Q$ 行: $\gcd(a_i,n)=1$ のとき、$a_i$ の $n$ を法とする位数($a_i^k\equiv1\pmod n$ となる最小の正整数 $k$)。$\gcd(a_i,n)\ne1$ のとき $-1$。
入力形式
n Q
a_1
...
a_Q
制約
| # | 条件 |
|---|---|
| 1 | $1\le n\le10^{12}$, $1\le Q\le10^4$ |
| 2 | $1\le a_i\le10^{12}$ |
入力例1
10 5
3
7
9
1
2出力例1
4
4
4
2
1
-1($\lambda(10)=\operatorname{lcm}(\lambda(2),\lambda(5))=\operatorname{lcm}(1,4)=4$。$9\equiv-1$ の位数は 2、$1$ の位数は 1、$\gcd(2,10)=2$ なので $-1$)
入力例2
561 3
2
5
560出力例2
80
40
80
2($561=3\cdot11\cdot17$ は最小の Carmichael 数。$\lambda=\operatorname{lcm}(2,10,16)=80$ で、$560=n-1\equiv-1$ の位数は 2)
入力例3
1024 3
3
5
1023出力例3
256
256
256
2($\lambda(2^{10})=2^{8}=256$。$\varphi(2^{10})=512$ ではない)
入力例4
1000000007 2
5
2出力例4
1000000006
1000000006
500000003(素数 $p$ では $\lambda(p)=p-1$。5 は原始根、2 の位数は $(p-1)/2$)
背景と出典
Carmichael 関数の定義は「$\lambda(p^e)=\varphi(p^e)$($p$ が奇素数、または $p^e\in\{2,4\}$)、$\lambda(2^e)=2^{e-2}$($e\ge3$)、$\lambda(\prod p_i^{e_i})=\operatorname{lcm}\lambda(p_i^{e_i})$」と記憶している。本セッションでは出典を確認していないので、下の検証ログの全探索(位数の最大値との一致)を根拠にする。
$\lambda(n)$ が $\varphi(n)$ より小さくなる $n$ は多く($n\le3000$ のうち 2285 個、実測)、また $n$ が Carmichael 数であることと「$n$ が平方因子を持たない合成数で、各素因数 $p$ について $p-1\mid n-1$」は同値(Korselt の判定法) と記憶している。後者は検証ログで $n\le10^6$ の 43 個を数えて確かめた。
この問題で確かめたいのは次の 3 点。(1) $\lambda(n)$ の式と位数の求め方が、$n\le800$ の全ての $(n,a)$ について全探索と一致するか。(2) $\lambda$ を作る式を誤る 2 通り(積を取る=結果は $\varphi(n)$ になる、$2^2$ を $2^{e-2}$ に含める)が何件で外れるか。(3) $n\approx10^{12}$ で、求めた位数が本当に最小か。
ヒント(クリックで段階的に開示)
ヒント1(方向性)
$a^k\equiv1\pmod n$ は、$n$ の素因数分解の各素数冪 $p^e$ で $a^k\equiv1\pmod{p^e}$ が成り立つことと同値(中国剰余定理)。したがって $k$ の候補は、各素数冪の位数の最小公倍数の倍数。
ヒント2(アプローチ)
全ての $a$ に共通の指数 $\lambda(n)$ をあらかじめ作る。$a$ の位数は $\lambda(n)$ の約数なので、$t=\lambda(n)$ から始め、$t$ の素因数 $q$ ごとに「$a^{t/q}\equiv1$ なら $t\leftarrow t/q$」を割れなくなるまで繰り返す。
ヒント3(誘導)
$\lambda(n)$ は素因数分解のかたち(素数 → 指数)で持つ。各素数冪について $p^{e-1}$ と、$p-1$ の素因数分解を、最大指数を取って混ぜる(最小公倍数)。$p=2$ は $e=1$ で 1、$e=2$ で 2、$e\ge3$ で $2^{e-2}$ と場合分けする。$p-1\le10^{12}$ の素因数分解は $\sqrt{10^{12}}=10^6$ までの試し割りで足りる。$Q$ 回の位数の計算は $\log\lambda$ 個の素因数ごとに pow を呼ぶ。
模範解答 (Python)
模範解答を表示する(まず自力で解いてから)
import sys
from math import gcd
def sieve(L):
sv = bytearray([1])*(L+1); sv[0]=sv[1]=0
for i in range(2, int(L**0.5)+1):
if sv[i]: sv[i*i::i] = bytearray(len(sv[i*i::i]))
return [i for i in range(L+1) if sv[i]]
PR = sieve(1000000)
def factor(x):
f = {}
for p in PR:
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 carmichael(fn):
"""λ(n) を素因数分解のかたち {素数: 指数} で返す。fn = n の素因数分解"""
lam = {}
def lcm_in(d):
for q, e in d.items():
if lam.get(q,0) < e: lam[q] = e
for p, e in fn.items():
if p == 2:
if e == 2: lcm_in({2:1})
elif e >= 3: lcm_in({2:e-2})
# e == 1 は λ(2)=1 で何も足さない
else:
if e > 1: lcm_in({p:e-1})
lcm_in(factor(p-1))
return lam
def order(a, n, lam):
"""gcd(a,n)=1 の a の n を法とする位数。λ(n) から素因数ごとに割っていく"""
t = 1
for q, e in lam.items(): t *= q**e
for q in lam:
while t % q == 0 and pow(a, t//q, n) == 1 % n: t //= q
return t
def main():
data = sys.stdin.read().split()
n, Q = int(data[0]), int(data[1])
lam = carmichael(factor(n))
L = 1
for q, e in lam.items(): L *= q**e
print(L)
for i in range(Q):
a = int(data[2+i])
print(order(a, n, lam) if gcd(a, n) == 1 else -1)
if __name__ == "__main__": main()
計算量: 素数の篩 $O(L\log\log L)$($L=10^6$)、$n$ の素因数分解と各 $p-1$ の分解が $O(\pi(L))$ ずつ、位数 1 回あたり(素因数の個数)×$O(\log n)$。実測(Python 3.14.7、M1 Mac)で $n=999999999989$(素数)、$Q=10^4$ が篩を除く本体 0.31 s。
Step-by-Step 解説
$p$ が奇素数なら $(\mathbb Z/p^e)^\times$ は巡回群で位数 $\varphi(p^e)=p^{e-1}(p-1)$、したがって $\lambda(p^e)=p^{e-1}(p-1)$。$p=2$ では $e=1$ が 1、$e=2$ が 2、$e\ge3$ では巡回でなく $\lambda(2^e)=2^{e-2}$。
$\lambda(n)=\operatorname{lcm}_i\lambda(p_i^{e_i})$。素因数分解で持てば、素数ごとに指数の最大を取るだけ。積にすると過大になる($n=15$ で $\lambda=\operatorname{lcm}(2,4)=4$、積だと 8)。
$a$ の位数は $\lambda(n)$ の約数。$t=\lambda(n)$ から、素因数 $q$ ごとに $a^{t/q}\equiv1$ である限り $t\leftarrow t/q$ とする。どの $q$ でも割れなくなった $t$ が最小。
$n=1$ では $\lambda(1)=1$、全ての $a$ の位数が 1。pow(a, t, 1) は 0 になるので、比較の右辺を 1 % n(= 0)にしておく。
合成数 $n$ について「$n$ が平方因子を持たず、$\lambda(n)\mid n-1$」なら、$n$ と互いに素な全ての $a$ で $a^{n-1}\equiv1$(Carmichael 数)。この判定に $\lambda$ をそのまま使える。
迷った他案と採らなかった理由
| 案 | 計算量 | 採否 | 理由 |
|---|---|---|---|
| λ(n) から素因数を割る(本解) | 位数 1 回あたり $O(\omega(\lambda)\log n)$ | 採用 | $n\le800$ の全 $(n,a)$ で一致 |
| φ(n) から素因数を割る | 同じ | 不採用 | 位数は φ の約数なので正しく出る(理屈のみで、この組み合わせは実測していない)が、$\lambda$ を出力する本問では結局 $\lambda$ が要る。$\varphi$ の素因数は $\lambda$ より多く、pow の回数が増える |
| 位数を 1, 2, 3, … と順に試す | $O(\operatorname{ord})$ | 検算用のみ | $n\le800$ でしか動かない |
| 素数冪ごとに位数を求めて LCM(CRT 風) | $O(\omega\cdot\text{位数})$ | 不採用 | 各素数冪での離散対数的な処理は要らず、$\lambda$ の素因数を割る方が単純 |
前提が変わったら:
- $n\le10^{18}$ では $\sqrt n=10^9$ の試し割りが重い。Miller–Rabin と Pollard の rho 法による素因数分解が要る。実装していない
- 位数でなく離散対数($a^x\equiv b$ を解く)を求める場合は、BSGS や Pohlig–Hellman が要る。位数を求める本解は Pohlig–Hellman の準備段階にあたる
- $a$ が $n$ と互いに素でない場合の周期(前周期+周期)を問うと、各素数冪ごとの前周期の長さが要る。本解は $-1$ を返すだけ
よくあるミス
| ミス | 原因 | 正しい書き方 |
|---|---|---|
| 素数冪の λ を積で合成する(結果は $\varphi(n)$ そのもの) | LCM と積を混同する | 素因数ごとに指数の最大を取る($n\le3000$ のうち 2285 個で $\lambda\ne\varphi$) |
| $\lambda(2^e)=\varphi(2^e)$ とする | $2^e$ が巡回群でないことを忘れる | $e\ge3$ で $2^{e-2}$(この誤りだけの件数は測っていない) |
| $\lambda(4)$ を 1 にする | $2^{e-2}$ を $e=2$ にも使う | $e=2$ は 2 を直接返す(外れるのは 3000 個中 $n=4$ の 1 個だが、$a=3$ の位数が 2 のところで確実に誤る) |
| $n=1$ で比較が通らない | pow(a,t,1) は 0 で、== 1 が偽 | 右辺を 1 % n にする |
| gcd を確かめずに位数を求める | $a$ と $n$ が互いに素でない | gcd(a,n)==1 でなければ $-1$ |
次のステップ
- 発展1: 原始根が存在する $n$($1,2,4,p^e,2p^e$)を $\lambda(n)=\varphi(n)$ で判定し、$n\le10^{12}$ で原始根を 1 つ求める
- 発展2: Korselt の判定法で、$10^{12}$ 以下の Carmichael 数を $n=p\cdot q\cdot r$ の形(素因数 3 個)に絞って列挙する
- 次回予告: 焦点帯 M1 から 3 問以上を含む通常のローテーション
検証ログ(本セッションで実行した数値)
- 全探索との照合(実測): $1\le n\le800$ の全ての $(n,a)$($\gcd(a,n)=1$)で、反復による位数と一致。各 $n$ で位数の最大値が $\lambda(n)$ と一致
- 誤った式(実測、$n\le3000$ について式の出力同士を比べた。$\lambda$ の式が全探索と一致したのは $n\le800$ まで): 積で合成した値は $\varphi(n)$ と一致し、$\lambda(n)$ と違う $n$ が 2285 個。$2^2$ を $2^{e-2}=1$ とすると $n=4$ の 1 個
- 最小性の確認(実測): $10^{11}\le n\le10^{12}$ の 40 個の $n$ で、$\gcd(a,n)=1$ の $a$ を 116 個選び、求めた位数 $o$ が $a^o\equiv1$ を満たし、$o$ の各素因数 $q$ で $a^{o/q}\not\equiv1$ になることを確認。$o$ の素因数分解は本解とは別実装の試し割りで行った
- Korselt の確認(実測): 平方因子なし・合成数・$\lambda(n)\mid n-1$ を満たす $n\le10^6$ は 43 個(先頭は 561, 1105, 1729, 2465, 2821, 6601, 8911, 10585)。先頭 5 個は $\gcd(a,n)=1$ の全ての $a$ で $a^{n-1}\equiv1$ を直接確認。$10^3,10^4,10^5,10^6$ 以下の個数は 1, 7, 16, 43 で、手元の記憶にある Carmichael 数の個数表と一致(出典は未確認)
- 入力例(実測): 出力例のとおり
- 実行時間(実測): $n=999999999989$、$Q=10^4$ で 0.31 s(素数の篩を除く)。$n=2^{39}\cdot3$ の $\lambda$ は 137438953472($2^{37}$)
- 扱っていない範囲: Pollard の rho 法、$n>10^{12}$、離散対数、$\gcd(a,n)\ne1$ の周期、Carmichael 数の個数表の出典の確認