@@ -18,6 +18,41 @@ public static void main(String[] args) {
18
18
}
19
19
20
20
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
+
21
56
private static final int LIMIT = 20000000 ;
22
57
23
58
private int [] smallestPrimeFactor ;
0 commit comments