2016 Update
This commit is contained in:
parent
948b86eafa
commit
dcf5d15da3
7965 changed files with 139854 additions and 31002 deletions
|
|
@ -1,10 +1,17 @@
|
|||
The '''multiplicative order''' of ''a'' relative to ''m'' is the least positive integer ''n'' such that ''a^n'' is 1 (modulo ''m'').
|
||||
For example, the multiplicative order of 37 relative to 1000 is 100 because 37^100 is 1 (modulo 1000), and no number smaller than 100 would do.
|
||||
|
||||
|
||||
;Example:
|
||||
The multiplicative order of 37 relative to 1000 is 100 because 37^100 is 1 (modulo 1000), and no number smaller than 100 would do.
|
||||
|
||||
|
||||
One possible algorithm that is efficient also for large numbers is the following: By the [[wp:Chinese_Remainder_Theorem|Chinese Remainder Theorem]], it's enough to calculate the multiplicative order for each prime exponent ''p^k'' of ''m'', and
|
||||
combine the results with the ''[[least common multiple]]'' operation.
|
||||
Now the order of ''a'' wrt. to ''p^k'' must divide ''Φ(p^k)''. Call this number ''t'', and determine it's factors ''q^e''. Since each multiple of the order will also yield 1 when used as exponent for ''a'', it's enough to find the least d such that ''(q^d)*(t/(q^e))'' yields 1 when used as exponent.
|
||||
|
||||
Now the order of ''a'' with regard to ''p^k'' must divide ''Φ(p^k)''. Call this number ''t'', and determine it's factors ''q^e''. Since each multiple of the order will also yield 1 when used as exponent for ''a'', it's enough to find the least d such that ''(q^d)*(t/(q^e))'' yields 1 when used as exponent.
|
||||
|
||||
|
||||
;Task:
|
||||
Implement a routine to calculate the multiplicative order along these lines. You may assume that routines to determine the factorization into prime powers are available in some library.
|
||||
|
||||
----
|
||||
|
|
@ -14,7 +21,7 @@ An algorithm for the multiplicative order can be found in Bach & Shallit, <i>Alg
|
|||
<p>Exercise 5.8, page 115:</p>
|
||||
|
||||
<p>Suppose you are given a prime<tt> p </tt>and a complete factorization
|
||||
of<tt> p-1</tt> .<tt> </tt>Show how to compute the order of an
|
||||
of<tt> p-1</tt>. Show how to compute the order of an
|
||||
element<tt> a </tt>in<tt> (Z/(p))<sup>*</sup> </tt>using<tt> O((lg p)<sup>4</sup>/(lg lg p)) </tt>bit
|
||||
operations.</p>
|
||||
|
||||
|
|
@ -22,8 +29,7 @@ operations.</p>
|
|||
|
||||
<p>Let the prime factorization of<tt> p-1 </tt> be<tt> q1<sup>e1</sup>q2<sup>e2</sup>...qk<sup>ek</sup></tt> .<tt> </tt>We use the following observation:
|
||||
if<tt> x^((p-1)/qi<sup>fi</sup>) = 1 (mod p)</tt> ,<tt> </tt>
|
||||
and<tt> fi=ei </tt>or<tt> x^((p-1)/qi<sup>fi+1</sup>) != 1 (mod p)</tt> ,<tt> </tt>then<tt> qi<sup>ei-fi</sup>||ord<sub>p</sub> x</tt> .<tt> </tt>
|
||||
(This follows by combining Exercises 5.1 and 2.10.)
|
||||
and<tt> fi=ei </tt>or<tt> x^((p-1)/qi<sup>fi+1</sup>) != 1 (mod p)</tt> ,<tt> </tt>then<tt> qi<sup>ei-fi</sup>||ord<sub>p</sub> x</tt>. (This follows by combining Exercises 5.1 and 2.10.)
|
||||
|
||||
Hence it suffices to find, for each<tt> i</tt> ,<tt> </tt>the exponent<tt> fi </tt> such that the condition above holds.</p>
|
||||
|
||||
|
|
@ -34,4 +40,5 @@ compute<tt> x1=a<sup>y1</sup>(mod p), ... , xk=a<sup>yk</sup>(mod p) </tt>.<tt>
|
|||
This can be done using<tt> O(k(lg p)<sup>3</sup>) </tt>bit operations, and<tt> k=O((lg p)/(lg lg p)) </tt>by Theorem 8.8.10.
|
||||
Finally, for each<tt> i</tt> ,<tt> </tt>repeatedly raise<tt> xi </tt>to the<tt> qi</tt>-th power<tt> (mod p) </tt>(as many as<tt> ei-1 </tt> times), checking to see when 1 is obtained.
|
||||
This can be done using<tt> O((lg p)<sup>3</sup>) </tt>steps.
|
||||
The total cost is dominated by<tt> O(k(lg p)<sup>3</sup>)</tt> ,<tt> </tt>which is<tt> O((lg p)<sup>4</sup>/(lg lg p))</tt> .
|
||||
The total cost is dominated by<tt> O(k(lg p)<sup>3</sup>)</tt> ,<tt> </tt>which is<tt> O((lg p)<sup>4</sup>/(lg lg p))</tt>.
|
||||
<br><br>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
require 'rational' # for lcm
|
||||
require 'mathn' # for prime_division
|
||||
require 'prime'
|
||||
|
||||
def powerMod(b, p, m)
|
||||
result = 1
|
||||
bits = p.to_s(2)
|
||||
for bit in bits.split('')
|
||||
p.to_s(2).each_char.inject(1) do |result, bit|
|
||||
result = (result * result) % m
|
||||
if bit == '1'
|
||||
result = (result * b) % m
|
||||
end
|
||||
bit=='1' ? (result * b) % m : result
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def multOrder_(a, p, k)
|
||||
|
|
@ -18,7 +12,7 @@ def multOrder_(a, p, k)
|
|||
t = (p - 1) * p ** (k - 1)
|
||||
r = 1
|
||||
for q, e in t.prime_division
|
||||
x = powerMod(a, t / q ** e, pk)
|
||||
x = powerMod(a, t / q**e, pk)
|
||||
while x != 1
|
||||
r *= q
|
||||
x = powerMod(x, q, pk)
|
||||
|
|
@ -28,15 +22,15 @@ def multOrder_(a, p, k)
|
|||
end
|
||||
|
||||
def multOrder(a, m)
|
||||
m.prime_division.inject(1) {|result, f|
|
||||
m.prime_division.inject(1) do |result, f|
|
||||
result.lcm(multOrder_(a, *f))
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
puts multOrder(37, 1000) # 100
|
||||
puts multOrder(37, 1000)
|
||||
b = 10**20-1
|
||||
puts multOrder(2, b) # 3748806900
|
||||
puts multOrder(17,b) # 1499522760
|
||||
puts multOrder(2, b)
|
||||
puts multOrder(17,b)
|
||||
b = 100001
|
||||
puts multOrder(54,b)
|
||||
puts powerMod(54, multOrder(54,b), b)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue