I want to find a fast algorithm to evaluate an expression like the following, where P is prime.
A ^ B ^ C ^ D ^ E mod P
Example:
(9 ^ (3 ^ (15 ^ (3 ^ 15)))) mod 65537 = 16134
The problem is the intermediate results can grow much too large to handle.
Basically the problem reduces to computing a^T mod m for given a, m and a term T that is ridiulously huge. However, we are able to evaluate T mod n with a given modulus n much faster than T . So we ask: "Is there an integer n, such that a^(T mod n) mod m = a^T mod m?"
Now if a and m are coprime, we know that n = phi(m) fulfills our condition according to Euler's theorem:
a^T (mod m)
= a^((T mod phi(m)) + k * phi(m)) (mod m) (for some k)
= a^(T mod phi(m)) * a^(k * phi(m)) (mod m)
= a^(T mod phi(m)) * (a^phi(m))^k (mod m)
= a^(T mod phi(m)) * 1^k (mod m)
= a^(T mod phi(m)) (mod m)
If we can compute phi(m) (which is easy to do for example in O(m^(1/2)) or if we know the prime factorization of m), we have reduced the problem to computing T mod phi(m) and a simple modular exponentiation.
What if a and m are not coprime? The situation is not as pleasant as before, since there might not be a valid n with the property a^T mod m = a^(T mod n) mod m for all T. However, we can show that the sequence a^k mod m for k = 0, 1, 2, ... enters a cycle after some point, that is there exist x and C with x, C < m, such that a^y = a^(y + C) for all y >= x.
Example: For a = 2, m = 12, we get the sequence 2^0, 2^1, ... = 1, 2, 4, 8, 4, 8, ... (mod 12). We can see the cycle with parameters x = 2 and C = 2.
We can find the cycle length via brute-force, by computing the sequence elements a^0, a^1, ... until we find two indices X < Y with a^X = a^Y. Now we set x = X and C = Y - X. This gives us an algorithm with O(m) exponentiations per recursion.
What if we want to do better? Thanks to Jyrki Lahtonen from Math Exchange for providing the essentials for the following algorithm!
Let's evaluate the sequence d_k = gcd(a^k, m) until we find an x with d_x = d_{x+1}. This will take at most log(m) GCD computations, because x is bounded by the highest exponent in the prime factorization of m. Let C = phi(m / d_x). We can now prove that a^{k + C} = a^k for all k >= x, so we have found the cycle parameters in O(m^(1/2)) time.
Let's assume we have found x and C and want to compute a^T mod m now.
If T < x, the task is trivial to perform with simple modular exponentiation. Otherwise, we have T >= x and can thus make use of the cycle:
a^T (mod m)
= a^(x + ((T - x) mod C)) (mod m)
= a^(x + (-x mod C) + (T mod C) + k*C) (mod m) (for some k)
= a^(x + (-x mod C) + k*C) * a^(T mod C) (mod m)
= a^(x + (-x mod C)) * a^(T mod C) (mod m)
Again, we have reduced the problem to a subproblem of the same form ("compute T mod C") and two simple modular exponentiations.
Since the modulus is reduced by at least 1 in every iteration, we get a pretty weak bound of O(P^(1/2) * min (P, n)) for the runtime of this algorithm, where n is the height of the stack. In practice we should get a lot better, since the moduli are expected to decrease exponentially. Of course this argument is a bit hand-wavy, maybe some more mathematically-inclined person can improve on it.
There are a few edge cases to consider that actually make your life a bit easier: you can stop immediately if m = 1 (the result is 0 in this case) or if a is a multiple of m (the result is 0 as well in this case).
EDIT: It can be shown that x = C = phi(m) is valid, so as a quick and dirty solution we can use the formula
a^T = a^(phi(m) + T mod phi(m)) (mod m)
for T >= phi(m) or even T >= log_2(m).
Related
I am a computer science student, I am studying the Algorithms course independently.
During the course I saw this question:
Show an efficient randomized algorithm to factor Carmichael numbers
(that is, we want a polynomial time algorithm, that given any
Carmichael number C, with probability at least 3/4 finds a nontrivial
factor of C). Hint: use the Rabin-Miller test.
my solution:
my idea is use Rabin-Miller test:
i will check if C is prime
i will use Rabin-Miller Primality tests steps:
Find n-1=c^k*m
choose a: 1 < a < n-1
compute b_0 = a^m(mod n), b_i = b_(i-1)^2 (mod n)
if b_0 = -/+1 this is prime, i will return nothing. if b_i = -1 this is prime, will return nothing. else if = 1 this is not prime i will return the factor of C.
algorithm:
function MillerRabinPrimality(n)
Input: integer n, Carmichael number
Output: return with probability 3/4 nontrivial factor of n
Find integers k,q > 0, q odd, so that (n-1)=2^(k)
Select a random integer a, 1<a<n-1
if a^q mod n = +/-1
return 'this prime'
for j = 0 to k-1 do
a = a^2 mod q
if (a = -1)
return 'this prime'
if (a = 1)
return 'this is composite, factor is ?'
i dont sure how to return the factor of c, for example i run Rabin-Miller Primality tests for 561, first carmichael number:
n = 561
n-1 = 2(^k)*m => 560
560/2^1 = 280 => 560/2^2 = 140 => 560/2^3 = 70 => **560/2^4 = 35**
k = 4
m = 35
choose a: 1<a<560
a = 2
b_0 = 2^35 mod 561 = 263
b_1 = 263^2 mod 561 = 166
b_2 = 166^2 mod 561 = 67
b_3 = 17^2 mod 561 = 1 --> composite
i found that 561 is composite but not sure how to return his factors (3 / 11 / 17)
If Miller–Rabin fails on a Carmichael number n, then as a byproduct you get some x ≢ ±1 mod n such that x² ≡ 1 mod n. Both gcd(x + 1, n) and gcd(x − 1, n) are proper divisors of n.
The proof: x ≢ 1 mod n is equivalent to x − 1 ≢ 0 mod n, which is equivalent to x − 1 not being divisible by n. Therefore gcd(x − 1, n) ≠ n. Likewise, x ≢ −1 mod n implies that gcd(x + 1, n) ≠ n.
On the other hand, x² ≡ 1 mod n is equivalent to (x + 1) (x − 1) being divisible by n, hence gcd((x + 1) (x − 1), n) = n. We cannot have gcd(x + 1, n) = 1, or else gcd(x − 1, n) = n (since gcd(a b, c) = gcd(a, c) for all b such that gcd(b, c) = 1). Likewise, gcd(x − 1, n) ≠ 1.
We know that sum of n terms in a Geometric Progression is given by
Sn = a1(1-r^n)/(1-r) if the series is of the form a1, a1*r, a1*r^2, a1*r^3....a1*r^n.
Now i have modified geometric progression where series is of the form
a1, (a1*r) mod p , (a1*r^2) mod p, (a1*r^3) mod p.....(a1*r^n)mod p where a1 is the initial term, p is prime number and r is common ratio. Nth term of this series is given by: (a1 * r^n-1) mod p.
I am trying to get summation formula for above modified GP and struggling very hard. If anyone can throw some light on it or advice on finding efficient algorithm for finding sum without iterating for all the n terms, will be of great help.
Note that if r is a primitive root modulo p.
Then we can reduce complexity of the sum.
We have to find S = a1*1 + a1*r + a1*r^2 + ... + a1*r^n. Then we write S in the closed form as S = a1*(r^n - 1) / (r - 1).
Now it can be reduced to:
a1*(r^n - 1) / (r - 1) = S (mod p)
=> a1*r^n = S * (r - 1) + 1 (mod p)
Now take discrete logarithm with base r both sides,
log(a1*r^n) = log_r(S*(r-1) + 1 (mod p))
=>log_r(a1) + n*log_r(r) = log_r(S*(r-1) + 1 (mod p))
=>n*log_r(r) = log_r(S*(r-1) + 1 (mod p)) - log_r(a1) (mod(p-1))
=>n*1 = log_r(S*(r-1) + 1 (mod (p-1))) - log_r(a1) (mod (p-1))
Note that if a1 is 1 then the last term is 0.
Let S = 6, r = 3, and m = 7, a1 = 1.
Then, we want to solve for n in the following congruence:
(3^n - 1)/(3 - 1) = 6 (mod 7)
=> 3^n - 1 = (3 - 1) * 6 (mod 7)
=> 3^n = 2 * 6 + 1 (mod 7)
=> 3^n = 6 (mod 7)
Then we take the discrete logarithm of both sides:
log_3(3^n) = log_3(6) (mod (7-1))
=> n * log_3(3) = log_3(6) (mod 6)
=> n * 1 = 3 (mod 6)
=> n = 3 (mod 6)
So, n = 3.
You can use Baby-step Giant-step algorithm to solve this in O(sqrt(m)).
If you want implementation in code I will provide you.
The principal relation is the same, the sum x is the solution of
a1*(r^N-1) = (r-1)*x mod p.
The difficulty to observe is that p and r-1 may have common divisors, which is not really a problem as r-1 divides into r^N-1, but still requires careful handling.
Modular division can be achieved via multiplication with the inverse and that can be computed via the extended Euclidean algorithm. Any implementation of
d,u,v = XGCD(r-1,p)
returns the largest common divisor d and Bezout factors u,v so that
u*(r-1)+v*p = d
Multiplication with f/d, f = a1*(r^N-1) results in
(u*f/d)*(r-1) + (v*f/d)*p = f = a1*(r^N-1)
so that the solution can be identified as x = u*(f/d). An implementation will thus follow the lines of
rN = powmod(r,N,p)
f = a1*(rN-1) mod p
d,u,v = XGCD(r-1,p)
return u*(f/d) mod p
Minimum standard random number generator.
I am reading about minimum standard number generator as below
Given a random integer xn, the next random integer in a random
sequence is given by computing xn+1 = a xn (mod m), where a = 7 ^ 5 =
16807 and m = 2^31 − 1 = 2147483647; as a check on your
implementation, if x0 = 1, then x10000 = 1043618065.
Park and Miller chose m as the largest Mersenne prime less than 2^32;
the smallest primitive root of m is 7, and since 5 is also prime, 7^5
is also a primitive root, hence their choice of a. Because a is a
primitive root of m, all values in the range 1 to m − 1 inclusive will
be generated before any repeat, so the random number generator has full
period. The multiplier a = 16807 has been shown to have good
randomness properties.
Subsequent to their original paper, Park and Miller recommended 48271
as an improvement, and some people use 69621, but we’ll continue to
use 16807. The easiest way to implement that is obvious: just
multiply a by the current value of x and compute the modulus.
But that may cause overflow in the intermediate multiplication,
rendering the results incorrect.
A trick of Linus Schrage allows that multiplication to be done without
overflow: Compute q = ⌊m / a⌋ and r = m (mod a) so that m = a q + r.
Then
a new x can be computed by hi = ⌊x / q⌋, lo = x (mod q), x = a · lo −
r · hi, then adding m to x if x ≤ 0.
My question is how author has computed new x in terms of as hi = floor(x/q) and lo = x(modq). I am looking for steps here. Kindly expain.
Let's simplify the notation. Set H = hi and L = lo. We have m = a * q + r. A simple calculation shows that q = 127773 and r = 2836. We observe that a < q.
Now let x_{n} be given and calculate H = x_{n} / q and L = x_{n} % q. So, x_{n} = q * H + L with L < q.
By definition x_{n+1} = a * x_{n} mod m. Calculating the right-hand-side (before reduction mod m) we get a * x_{n} = a * (q * H + L) = a * q * H + a * L = (m - r) * H + a * L = m * H - r * H + a * L.
Now let's consider r * H. Clearly 0 <= r * H < a * (x_{n} / q). As x_{n} < m and as observed above a < q, a * (x_{n} / q) < m. In particular, it doesn't overflow.
Likewise 0 < a * L < a * q < m. So, again no overflow.
We conclude that x_{n+1} = m * H - r * H + a * L. Reducing the latter modulo m we get x_{n+1} = -r * H + a * L with neither of the two right-hand-side expressions overflowing m. If the sum is negative we add m and we are done.
if x:
for i in range(a):
for z in range(a):
for k in range(z):
for p in range(i):
c = (i * z) + (k * p)
else:
for i in range(a):
for z in range(a):
for k in range(z):
c = (i * z) + (k * p)
Would this be O(n^4)? Also, how many multiplications would occur?
EDIT: updated the code. Also, since the lower bound captures the max number of steps a valid input will force, wouldn't big omega be n^4 as well?
Yes, the complexity is still O(n^4). To make things simple, here is the trick to rearrange your code
for i in range(a):
for p in range(i):
f(i, p)
where f(i, p) is
for z in range(a):
for k in range(z):
c = (i * z) + (k * p)
In the first part, f(i, p) has been executed for O(n^2/2) up to the largest order (because of the summation sum_i (i^2), do the math yourself). Similarly, the f(i, p) has the complexity of f(i, p) which is again equal to O(n^2/2).
So the combined resulting order is O(n^4/4). and there is two multiplications for each operation, so number of multiplication is O(n^4/2)
The following code would only be O(n4) if all the numbers a, z, and i were O(n).
for i in range(a):
for z in range(a):
for k in range(z):
for p in range(i):
c = (i * z) + (k * p)
As you've written it, all we know is that that code block is O(a2zi). Similarly, the total number of multiplications that would occur would be: 2a2zi. And, again, if a, z, and i are all O(n), the number of multiplications would be O(n4).
I'm not sure what you want to know about the second block of code.
Is there faster algo to calculate (n! modulo m).
faster than reduction at every multiplication step.
And also
Is there faster algo to calculate (a^p modulo m) better than right-left binary method.
here is my code:
n! mod m
ans=1
for(int i=1;i<=n;i++)
ans=(ans*i)%m;
a^p mod m
result=1;
while(p>0){
if(p%2!=0)
result=(result*a)%m;
p=(p>>1);
a=(a*a)%m;
}
Now the a^n mod m is a O(logn), It's the Modular Exponentiation Algorithm.
Now for the other one, n! mod m, the algorithm you proposed is clearly O(n), So obviously the first algorithm is faster.
The standard trick for computing a^p modulo m is to use successive square. The idea is to expand p into binary, say
p = e0 * 2^0 + e1 * 2^1 + ... + en * 2^n
where (e0,e1,...,en) are binary (0 or 1) and en = 1. Then use laws of exponents to get the following expansion for a^p
a^p = a^( e0 * 2^0 + e1 * 2^1 + ... + en * 2^n )
= a^(e0 * 2^0) * a^(e1 * 2^1) * ... * a^(en * 2^n)
= (a^(2^0))^e0 * (a^(2^1))^e1 * ... * (a^(2^n))^en
Remember that each ei is either 0 or 1, so these just tell you which numbers to take. So the only computations that you need are
a, a^2, a^4, a^8, ..., a^(2^n)
You can generate this sequence by squaring the previous term. Since you want to compute the answer mod m, you should do the modular arithmetic first. This means you want to compute the following
A0 = a mod m
Ai = (Ai)^2 mod m for i>1
The answer is then
a^p mod m = A0^e0 + A1^e1 + ... + An^en
Therefore the computation takes log(p) squares and calls to mod m.
I'm not certain whether or not there is an analog for factorials, but a good place to start looking would be at Wilson's Theorem. Also, you should put in a test for m <= n, in which case n! mod m = 0.
For the first computation, you should only bother with the mod operator if ans > m:
ans=1
for(int i=1;i<=n;i++) {
ans *= i;
if (ans > m) ans %= m;
}
For the second computation, using (p & 1) != 0 will probably be a lot faster than using p%2!=0 (unless the compiler recognizes this special case and does it for you). Then the same comment applies about avoiding the % operator unless necessary.