1. 模取幂问题
计算模取幂a^n mod m时,可使用如下算法(偷懒一下,直接给scheme代码),时间复杂度为log(n),效率很高。
(define (expmod base exp m)
(cond ((= exp 0) 1)
((even? exp)
(remainder (square (expmod base (/ exp 2) m)) m))
(else
(remainder (* base (expmod base (- exp 1) m)) m))))
但当指数n不直接给出,而是由其他函数定义时,上述算法可能不太适用。例如计算a^(b^n) mod m,无法按照上述算法直接对n进行降次。
按照一般的经验,序列a^n mod m, n=1,2,3...是具有周期性的,例如下面分别计算当a=2和3,m=7和11,序列的前20项如下,其周期分别为3和5
1 ]=> (map (lambda (x) (expmod 2 x 7)) (iota 20 1))
;Value 11: (2 4 1 2 4 1 2 4 1 2 4 1 2 4 1 2 4 1 2 4)1 ]=> (map (lambda (x) (expmod 3 x 11)) (iota 20 1));Value 12: (3 9 5 4 1 3 9 5 4 1 3 9 5 4 1 3 9 5 4 1)
假如能够计算出序列a^n mod m的周期t,则a^(b^n) mod m的问题可通过b^n mod t来间接计算。
寻找周期t的一个很自然的方法为,通过计算序列有限项数,在其中搜索循环部分的长度,但该方法不太准确,且周期t很大时,需要计算很多项,效率不高。
下面介绍一种使用数论中的欧拉Φ函数和欧拉定理计算模取幂序列周期的方法。
2. 欧拉Φ函数
欧拉Φ函数Φ(n)定义为不大于n且和n互素的正整数的个数,例如小于10且与其互素的正整数有1, 3, 7, 9,所以Φ(10)=4.
欧拉Φ函数有如下重要性质,
(1) 对于任意素数p, 有Φ(p) = p-1
(2) 欧拉Φ函数为乘性函数,即Φ(mn) = Φ(m)Φ(n), m,n均为正整数
(3) 设n的素因数分解形式为 (p1^k1) * (p2^k2) *...* (ps^ks), pi均为素数,ki≥0,则
Φ(n) = n(1-1/p1)(1-1/p2)...(1-1/ps)
3. 欧拉定理
对于互素的正整数a和n,a^Φ(n) ≡ 1 (mod n)
4. 模取幂的周期
设序列a(n) = a^n mod m, a,n,m均为正整数, n≥1, a>1, m>1,
令d = gcd(a, m), d≥1
a = d*a',
n = (d^s)*q, s≥1, q≥1, 且gcd(d, q)=1,
有如下结论成立:
1. 如果d=1, 有a(k) = a(k+t), k≥1, t=Φ(m),即序列a(n)从第1项开始, 以周期t循环;
2. 如果d>1, 有a(k) = a(k+t), k≥s, t=Φ(m),即序列a(n)从第s项开始, 以周期t循环;
3. 如果d>1, 且q=1, 有a(k) = 0, k≥s,即序列a(n)从第s项开始全部为0
注1:上述t不一定是最小周期
5. 证明:
1. 根据欧拉定理, 如果gcd(a, m)=1, 则有a^Φ(m) ≡ 1 (mod m), 所以
a(k+t) = a^(k+Φ(m)) mod m
= (a^k mod m) * (a^Φ(m) mod m) mod m
= a^k mod m
= a(k)
结论1得证
2. 设序列d(n) = d^n mod m, a'(n) = a'^n mod m, 则
a(n) = a^n mod m
= (d*a')^n mod m
= ((d^n mod m) * (a'^n mod m)) mod m
= (d(n) * a'(n)) mod m
下面分别证明从第s项开始,序列d(n)和a'(n)有共同的周期t=Φ(m)
由于gcd(a', m)=1, 根据上述结论1, 对于序列a'(n), 有
a'(k) = a'(k+t), k≥1, t=Φ(m)
即序列a'(k)从第1项开始,以周期t循环,显然从第s项开始,循环周期依然为t。
由于gcd(d, q)=1, 根据结论1, 有
d^k mod q = d^(k+r) mod q, k≥1, r=Φ(q), 即
q | (d^(k+r) - d^k,
两边同时乘以d^s, 有
(d^s)*q | d^(s+k+r) - d^(s+k), 即
d^(s+k+r) mod m = d^(s+k) mod m, 即
d(k) = d(k+r), k≥s, r=Φ(q)
由于欧拉函数为乘性函数, 有Φ(m) = Φ(d^s)Φ(q), 所以Φ(q)|Φ(m), 即
r|t, 所以t也是上述序列d(k)的周期, 即
d(k) = d(k+t), k≥s, t=Φ(m)
即序列d(k)从第s项开始,已周期t循环。
根据上述分析, 当k≥s时, 序列d(n)和a'(n)有相同的周期t=Φ(m), 所以
a(k) = (d(k) * a'(k)) mod m
= (d(k+t) * a'(k+t)) mod m
= a(k+t)
结论2得证
3. 当q=1时, d(s) = d^s mod m = 0, 且对于任意k>0, 有
d(s+k) = (d(s) * d^k) mod m = 0
结论3得证