Implement the function fast modular exponentiation - python

I am trying to implement the function fast modular exponentiation(b, k, m) which computes:
b(2k) mod m using only around 2k modular multiplications.
I tried this method:
def FastModularExponentiation(b, k, m):
res = 1
b = b % m
while (k > 0):
if ((k & 1) == 1):
res = (res * b) % m
k = k >> 1
b = (b * b) % m
return res
but I am still stuck in same problem which is if I try b = 2, k = 1, m = 10, my code returns 22. However, the correct answer is:
2^(2^1) mod 10 = 2^2 mod 10 = 4
and I cannot find the reason why.

Update: I finally understood that you do not want regular modular exponentiation (i.e., b^k mod m), but b^(2^k) mod m (as you plainly stated).
Using the regular built-in Python function pow this would be:
def FastModularExponentiation(b, k, m):
return pow(b, pow(2, k), m)
Or, without using pow:
def FastModularExponentiation(b, k, m):
b %= m
for _ in range(k):
b = b ** 2 % m
return b
If you know r = phi(m) (Euler's totient function), you could reduce the exponent first: exp = pow(2, k, r) and then calculate pow(b, exp, m). Depending on the input values, this might speed things up.
(This was the original answer when I thought you wanted, b^k mod m)
This is what works for me:
def fast_mod_exp(b, exp, m):
res = 1
while exp > 1:
if exp & 1:
res = (res * b) % m
b = b ** 2 % m
exp >>= 1
return (b * res) % m
The only significant differences I spot is in the last line: return (b * res) % m and that my while loop terminates earlier: while exp > 1 (which should be the same thing you do - except it saves an unnecessary squaring operation).
Also note that the built-in function pow will do all that for free (if you supply a third argument):
pow(4, 13, 497)
# 445

def fast_exponentiation(k, x, q):
# make sure all variables are non-negative
assert (k >= 0 and x >= 0 and q >=1)
result = 1 # define a counter
while x:
if x % 2 == 1:
result = (result * k) % q
k = (k ^ 2) % q
x >> = 1 # bit shift operator, dividing x by 2 ** y thus x >> 2 ** 1 = x / 2
return result

Related

RSA Cryptography shows wrong result for large prime numbers

I implemented a RSA Cryptography program, using python, and it works perfectly using prime numbers with aproximally 10 digits. But when I use numbers with 25 digits or more, for example, it does not work.
It worked with the following keys:
p = 2324731
q = 186647
e = 433899328297
n = 433904066957
It not worked with:
p = 3673864730662357928718503
q = 2127738717256957618781057
e = 7817024229395103552360986476332293342120062315901
n = 7817024229395103552360993847944520620136941797671
here's the code:
inverse (d key):
#classmethod
def __linearOperation(cls, a, b, mdc, i):
t = -int(a / b)
r = a % b
mdc.append([1, a, t, b])
if r == 1:
return mdc
inverseLine = cls.__linearOperation(b, r, mdc, i + 1)
s = inverseLine[i][0]
t = inverseLine[i][2]
inverseLine[i - 1][0] *= t
inverseLine[i - 1][2] *= t
inverseLine[i - 1][2] += s
inverseLine.remove(inverseLine[i])
return inverseLine
def __inverse(self, e, φ):
inverseLine = self.__linearOperation(e, φ, [], 1)
inverse = inverseLine[0][0]
if inverse < 0:
return inverse + φ
if inverse > φ:
return inverse % φ
else:
return inverse
Modular Exponentiation:
#staticmethod
def __QuickMod(base, exp, n):
result = 1
while exp > 0:
if exp & 1:
result = (result * base) % n
base = (base ** 2) % n
exp = exp >> 1
return result
encrypt/decrypt:
def encryptChar(self, n: int, e: int, M: int) -> int:
C = self.__QuickMod(M, e, n) # C = M^e mod n
return C
def decryptChar(self, p: int, q: int, e: int, C: int) -> int:
d = self.__inverse(e, (p - 1) * (q - 1))
M = self.__QuickMod(C, d, p * q) # M = C^d mod n
return M
By trying to encrypt the number 109 ("m" char in ascII), the encryptChar function returns 6825028446539883496812231478440519650519629664279.
By trying to decrypt the number above the decryptChar function should returns the number 109 back. But that's not what happens.
In my conception, by using python we do not have number size restriction.
Is there something i'm not seeing? Thank you for your help.
The problem is in my inverse algorithm. I'll try to re-implement it. But using pow() function with -1 as expoent works.

Given a rod of length N , you need to cut it into R pieces , such that each piece's length is positive, how many ways are there to do so?

Description:
Given two positive integers N and R, how many different ways are there to cut a rod of length N into R pieces, such that the length of each piece is a positive integer? Output this answer modulo 1,000,000,007.
Example:
With N = 7 and R = 3, there are 15 ways to cut a rod of length 7 into 3 pieces: (1,1,5) , (1,5,1), (5,1,1) , (1,2,4) , (1,4,2) (2,1,4), (2,4,1) , (4,1,2), (4,2,1) , (1,3,3), (3,1,3), (3,3,1), (2,2,3), (2,3,2), (3,2,2).
Constraints:
1 <= R <= N <= 200,000
Testcases:
N R Output
7 3 15
36 6 324632
81 66 770289477
96 88 550930798
My approach:
I know that the answer is (N-1 choose R-1) mod 1000000007. I have tried all different ways to calculate it, but always 7 out of 10 test cases went time limit exceeded. Here is my code, can anyone tell me what other approach I can use to make it in O(1) time complexity.
from math import factorial
def new(n, r):
D = factorial(n - 1) // (factorial(r - 1) * factorial(n - r))
return (D % 1000000007)
if __name__ == '__main__':
N = [7, 36, 81, 96]
R = [3, 6, 66, 88]
answer = [new(n, r) for n,r in zip(N,R)]
print(answer)
I think there's two big optimizations that the problem is looking for you to exploit. The first being to cache intermediate values of factorial() to save computational effort across large batches (large T). The second optimization being to reduce your value mod 1000000007 incrementally, so your numbers stay small, and multiplication stays a constant-time. I've updated the below example to precompute a factorial table using a custom function and itertools.accumulate, instead of merely caching the calls in a recursive implementation (which will eliminate the issues with recursion depth you were seeing).
from itertools import accumulate
MOD_BASE = 1000000007
N_BOUND = 200000
def modmul(m):
def mul(x, y):
return x * y % m
return mul
FACTORIALS = [1] + list(accumulate(range(1, N_BOUND+1), modmul(MOD_BASE)))
def nck(n, k, m):
numerator = FACTORIALS[n]
denominator = FACTORIALS[k] * FACTORIALS[n-k]
return numerator * pow(denominator, -1, m) % m
def solve(n, k):
return nck(n-1, k-1, MOD_BASE)
Running this against the example:
>>> pairs = [(36, 6), (81, 66), (96, 88)]
>>> print([solve(n, k) for n, k in pairs])
[324632, 770289477, 550930798]
I literally translated code from accepted answer of Ivaylo Strandjev here and it works much faster:
def get_degree(n, p):# { // returns the degree with which p is in n!
degree_num = 0
u = p
temp = n
while (u <= temp):
degree_num += temp // u
u *= p
return degree_num
def degree(a, k, p):
res = 1
cur = a
while (k):
if (k % 2):
res = (res * cur) % p
k //= 2
cur = (cur * cur) % p
return res
def CNKmodP( n, k, p):
num_degree = get_degree(n, p) - get_degree(n - k, p)
den_degree = get_degree(k, p)
if (num_degree > den_degree):
return 0
res = 1
for i in range(n, n - k, -1):
ti = i
while(ti % p == 0):
ti //= p
res = (res * ti) % p
denom = 1
for i in range(1, k + 1):
ti = i
while(ti % p == 0):
ti //= p
denom = (denom * ti) % p
res = (res * degree(denom, p-2, p)) % p
return res
To apply this approach, you just need to call
result = CNKmodP(n-1, r-1, 1000000007)
In Java we can use BigInteger because the value of factorials that we calculate may not fit in integer. Additionally BigInteger provides built in methods multiply and divide.
static int CNRmodP(int N, int R, int P) {
BigInteger ret = BigInteger.ONE;
for (int i = 0; i < R; i++) {
ret = ret.multiply(BigInteger.valueOf(N - i))
.divide(BigInteger.valueOf(i + 1));
}
BigInteger p = BigInteger.valueOf(P);
//Calculate Modulus
BigInteger answer = ret.mod(p);
//Convert BigInteger to integer and return it
return answer.intValue();
}
To apply the above approach, you just need to call
result = CNRmodP(N-1, R-1, 1000000007);

Given N, return M that satisfy the equation: N + M = 2 * (N XOR M)

Problem
Given N, return M that satisfy the equation: N + M = 2 * (N ^ M)
Constraints
1 <= Test Cases = 10^5;
1 <= N <= 10^18
I came across this problem in one of the hiring challenges.
By trial and error method, I have found a pattern that - Such an M exists between N/3 and 3N and that N + M is an Even number. So I code it up and upon submission, my solution only managed to pass only half of the test cases. This is not much of an optimisation as this method's time complexity is same as that of Brute force solution.
I know that my solution is not the Optimal solution.
Here's my solution:
def solve(n):
m = n//3
end = 3*n
# If both m and n are odd/even, their sum will be even
if (m&1 == 1 and n & 1 == 1) or (m&1 == 0 and n&1 == 0):
inc = 2
else:
m += 1
inc = 2
while m <= end:
if (n + m) == 2 * (n ^ m):
return m
m += inc
Could someone provide me some hints/methods/algorithm to get an Optimal Solution. Thanks!
The bottom bit of m is determined (since n+m must be even). Given that bottom bit, the next bit is determined, and so on.
That observation leads to this O(log n) solution:
def solve(n):
b = 1
m = 0
while n + m != 2 * (n ^ m):
mask = 2 * b - 1
if ((n + m) & mask) != ((2 * (n ^ m)) & mask):
m += b
b *= 2
return m
Another way to implement this is to find the smallest bit in which m+n and 2*(n^m) differ, and toggle that bit in m. That results in this very compact code (using the new walrus operator, and some bit-twiddling tricks):
def solve(n):
m = 0
while r := n + m ^ 2 * (n ^ m):
m |= r & -r
return m

Factoring RSA primes, p and q, given n, e and d. SageMath implementation. I am receiving an error

n=3046489427752548614835705731738608655336037381904612690933920645578584306854679988103697087282316860957470393164677006321152198903148509969091675769600609
e=65537
d=2423357597198465971720020922639076344965108271563411031993639487546008469794786697722604241075597290450041126457953384566271052978353705415054748363082433
b = e * d - 1
print(b) # b sayısının ilk halini görmek için
while (b % 2 == 0):
b = b /2
else:
t = b
print(t) # b 2'ye sürekli olarak bölündü ve bölünemeyen kısmı da t olarak kaldı.
a = 2
while (a < n):
x = power_mod(a, t, n) - 1
d = gcd (x,n)
a += 1
if (factorial(d) == 1) and (factorial(d) == n):
p = d
q = n // d
break
print(p)
print(q)
Here is my code, above. I need to factor n into primes p and q. However, SageMath giving me this error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-23-d05a9147cce3> in <module>
17 a = Integer(2)
18 while (a < n):
---> 19 x = power_mod(a, t, n) - Integer(1)
20 d = gcd (x,n)
21 a += Integer(1)
/ext/sage/sage-9.2/local/lib/python3.8/site-packages/sage/arith/misc.py in power_mod(a, n, m)
2200
2201 apow = a % m
-> 2202 while n&1 == 0:
2203 apow = (apow*apow) % m
2204 n = n >> 1
TypeError: unsupported operand type(s) for &: 'sage.rings.rational.Rational' and 'int'
What might be the problem? This is my first program. I am going insane.
I have edited some parts after my professor made a comment.
if (d != 1) and (d != n):
Here, I thought "!" was factorial. Even though I fixed it, nothing has changed. I am receiving the same error.
It is due to the fact that b is not an integer but a rational number. Even though b / 2 outputs a number with a nil fractional part, it is still considered as a rational (like 1.0 instead of 1). Fast modular exponentiation cannot deal with rational numbers, hence the error.
I tried your code and got the same error as you. I solved it by performing a division over integers when computing b, like this:
while (b % 2 == 0):
b = b // 2
Note that print(t) fools you by making you believe that t is an integer, while it is actually a rational. You can print type(t) to prove it.
Okay, I fixed the problem. I submitted my assignment. Here is the final code. It works perfectly well.
b = e * d - 1
while (b % 2 == 0):
b = b /2
else:
t = int(b)
a = 2
while (a < n):
x = power_mod(a, t, n) - 1
d = gcd (x,n)
a += 1
if (d != 1) and (d != n):
p = d
q = n // d
print(d)
print(n // d)
break

How to find mod of large numbers?

How to find (a^(b^c)) % (10^9 + 7) in Python for large inputs?
My code just get terminated after a few test cases.
My code:
numbers = list(map(int, input().split()))
x = numbers[2]
y = numbers[1]
z = numbers[0]
m = pow(10,9) + 7
a = pow(y,x)
r = z % m
for i in range (0,a):
r = r*z
r = r % m
print(r)
You should use Fermat's Little Theorem and Pingala's algorithm for power.
a ^ (p - 1) is 1 so if you take (b ^ c) % (10 ^ 9 + 6) that will become 1 (after taking power of a) and for calculating power modulo a number you can use binary approach that is a^2k % M = ((a^k % M)^2) % M and a ^ (2k + 1) % M = ((a % M) * (a^k % M) ^ 2) % M.
f a b c p = modPow a (modPow b c (p - 1)) p
modPow x n p
| n == 0 = 1
| even n =
let val = x ^ (n `div` 2)
in (val * val) `mod` p
| otherwise = (x * modPow x (n-1) p) `mod` p

Categories

Resources