Skip to content

Commit d4146ca

Browse files
committed
P451: Added explanation to Java and Python solutions.
1 parent 0e28286 commit d4146ca

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

java/p451.java

+35
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,41 @@ public static void main(String[] args) {
1818
}
1919

2020

21+
/*
22+
* Let n be an arbitrary integer such that n >= 3.
23+
* When we say that the modular inverse of m modulo n equals m itself,
24+
* the formula is m^-1 = m mod n, which is equivalent to m^2 = 1 mod n.
25+
*
26+
* We know that if n is prime, then m^2 = 1 mod n has exactly two solutions:
27+
* m = 1, n-1. It is easy to verify that these two numbers are solutions.
28+
* The equation factorizes as (m - 1)(m + 1) = 0 mod n. Because n is prime,
29+
* the numbers form a field, and there are no zero divisors (two arbitrary
30+
* non-zero numbers x and y such that xy = 0). Hence 1 and -1 mod n are
31+
* the only possible solutions to the equation. (Note that for the excluded
32+
* special prime case where n = 2, the solutions 1 and -1 are the same number.)
33+
*
34+
* Suppose we can find the smallest prime factor of n quickly. (Note that if n is
35+
* prime, then the smallest prime factor is n itself.) This can be achieved by
36+
* building a table ahead of time, using a modification of the sieve of Eratosthenes.
37+
*
38+
* Suppose that for every n' < n, we know the set of solutions to m^2 = 1 mod n'.
39+
* This means whenever we solve the equation for the number n, we save its solutions
40+
* in an ever-growing list, so that when we work on the next value of n we can access
41+
* all possible smaller solutions. This is essentially an argument by strong induction.
42+
*
43+
* Let p be the smallest prime factor of n. If p = n, then the set of
44+
* solutions is {1, n - 1}, and we are finished with this value of n.
45+
*
46+
* Otherwise p < n, and obviously n is an integer multiple of p. Because we are looking
47+
* for values of m such that m^2 = 1 mod n, these candidate m values also must satisfy
48+
* m^2 = 1 mod k for any k that divides n (i.e. k is a factor of n). We look at the set
49+
* of solutions for the modulus k = n/p, which has already been solved because k < n.
50+
* We know that any solution modulo n must be congruent to these solutions modulo k.
51+
* Hence we can try to extend and check these old solutions by brute force. Namely, suppose
52+
* m' is a solution modulo k. Then we check the sequence m = m' + 0k, m' + 1k, m' + 2k, ...,
53+
* m' + (p-1)k modulo n. Because p is usually a small number, this isn't a lot of work to do.
54+
*/
55+
2156
private static final int LIMIT = 20000000;
2257

2358
private int[] smallestPrimeFactor;

python/p451.py

+32
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,38 @@
99
import array, eulerlib, itertools
1010

1111

12+
# Let n be an arbitrary integer such that n >= 3.
13+
# When we say that the modular inverse of m modulo n equals m itself,
14+
# the formula is m^-1 = m mod n, which is equivalent to m^2 = 1 mod n.
15+
#
16+
# We know that if n is prime, then m^2 = 1 mod n has exactly two solutions:
17+
# m = 1, n-1. It is easy to verify that these two numbers are solutions.
18+
# The equation factorizes as (m - 1)(m + 1) = 0 mod n. Because n is prime,
19+
# the numbers form a field, and there are no zero divisors (two arbitrary
20+
# non-zero numbers x and y such that xy = 0). Hence 1 and -1 mod n are
21+
# the only possible solutions to the equation. (Note that for the excluded
22+
# special prime case where n = 2, the solutions 1 and -1 are the same number.)
23+
#
24+
# Suppose we can find the smallest prime factor of n quickly. (Note that if n is
25+
# prime, then the smallest prime factor is n itself.) This can be achieved by
26+
# building a table ahead of time, using a modification of the sieve of Eratosthenes.
27+
#
28+
# Suppose that for every n' < n, we know the set of solutions to m^2 = 1 mod n'.
29+
# This means whenever we solve the equation for the number n, we save its solutions
30+
# in an ever-growing list, so that when we work on the next value of n we can access
31+
# all possible smaller solutions. This is essentially an argument by strong induction.
32+
#
33+
# Let p be the smallest prime factor of n. If p = n, then the set of
34+
# solutions is {1, n - 1}, and we are finished with this value of n.
35+
#
36+
# Otherwise p < n, and obviously n is an integer multiple of p. Because we are looking
37+
# for values of m such that m^2 = 1 mod n, these candidate m values also must satisfy
38+
# m^2 = 1 mod k for any k that divides n (i.e. k is a factor of n). We look at the set
39+
# of solutions for the modulus k = n/p, which has already been solved because k < n.
40+
# We know that any solution modulo n must be congruent to these solutions modulo k.
41+
# Hence we can try to extend and check these old solutions by brute force. Namely, suppose
42+
# m' is a solution modulo k. Then we check the sequence m = m' + 0k, m' + 1k, m' + 2k, ...,
43+
# m' + (p-1)k modulo n. Because p is usually a small number, this isn't a lot of work to do.
1244
def compute():
1345
LIMIT = 20000000
1446

0 commit comments

Comments
 (0)