|
| 1 | +""" |
| 2 | +PROBLEM |
| 3 | +
|
| 4 | +For a prime p let S(p) = (sum (p-k)!) mod p for 1 <= k <= 5. |
| 5 | +
|
| 6 | +For example, if p=7, |
| 7 | +
|
| 8 | +(7-1)! + (7-2)! + (7-3)! + (7-4)! + (7-5)! = 6! + 5! + 4! + 3! + 2! = 720+120+24+6+2 = 872. |
| 9 | +
|
| 10 | +As 872 mod (7) = 4, S(7) = 4. |
| 11 | +
|
| 12 | +It can be verified that sum S(p) = 480 for 5 <= p < 100. |
| 13 | +
|
| 14 | +Find sum S(p) for 5 <= p < 10^8. |
| 15 | +
|
| 16 | +ANSWER: 139602943319822 |
| 17 | +Solve time: 3.661 seconds |
| 18 | +""" |
| 19 | + |
| 20 | +import unittest |
| 21 | +from util.utils import timeit, primes_upto |
| 22 | + |
| 23 | + |
| 24 | +# with Wilson's theorem, we know that (p-1)! = -1 mod p |
| 25 | +# so we can rewrite the sum as: |
| 26 | +# S(p) = (\sum_{k=1}^{5} (p-k)!) mod p |
| 27 | + |
| 28 | +# (p-1)! = -1 mod p |
| 29 | +# (p-2)! = -1/(p-1) = -1/(-1) = 1 mod p |
| 30 | +# (p-3)! = 1/(p-2) = 1/(-2) = -1/2 mod p |
| 31 | +# (p-4)! = (-1/2)/(p-3) = (-1/2)/(-3) = 1/6 mod p |
| 32 | +# (p-5)! = (1/6)/(p-4) = (1/6)/(-4) = -1/24 mod p |
| 33 | +# so S(p) = (-1 + 1 - 1/2 + 1/6 - 1/24) mod p = (-12 + 4 - 1)/24 = -9/24 = -3/8 mod p |
| 34 | + |
| 35 | +# 1/(p-1) mod p = x such that x * (p-1) = 1 mod p |
| 36 | +# x * (-1) = 1 mod p |
| 37 | +# x = -1 mod p |
| 38 | + |
| 39 | +# 1/(p-2) mod p = x such that x * (p-2) = 1 mod p |
| 40 | +# x * (-2) = 1 mod p |
| 41 | +# x = -1/2 mod p |
| 42 | + |
| 43 | +# 1/(p-3) mod p = x such that x * (p-3) = 1 mod p |
| 44 | +# x * (-3) = 1 mod p |
| 45 | +# x = -1/3 mod p |
| 46 | + |
| 47 | +# 1/(p-4) mod p = x such that x * (p-4) = 1 mod p |
| 48 | +# x * (-4) = 1 mod p |
| 49 | +# x = -1/4 mod p |
| 50 | + |
| 51 | +# 1/(p-5) mod p = x such that x * (p-5) = 1 mod p |
| 52 | +# x * (-5) = 1 mod p |
| 53 | +# x = -1/5 mod p |
| 54 | + |
| 55 | +# We need to find the sum of S(p) for all primes 5 <= p < N |
| 56 | +# S(p) = -3/8 mod p |
| 57 | + |
| 58 | +# example N = 100 |
| 59 | +# S(5) = -3/8 mod 5 = -3 * 2 mod 5 = -6 mod 5 = 4 |
| 60 | +# S(7) = -3/8 mod 7 = -3 * 6 mod 7 = -18 mod 7 = 4 |
| 61 | +# S(11) = -3/8 mod 11 = -3 * 7 mod 11 = -21 mod 11 = 1 |
| 62 | +# S(13) = -3/8 mod 13 = -3 * 5 mod 13 = -15 mod 13 = 11 |
| 63 | +# S(17) = -3/8 mod 17 = -3 * 15 mod 17 = -45 mod 17 = 11 |
| 64 | +# S(19) = -3/8 mod 19 = -3 * 12 mod 19 = -36 mod 19 = 2 |
| 65 | +# S(23) = -3/8 mod 23 = -3 * 14 mod 23 = -42 mod 23 = 4 |
| 66 | +# S(29) = -3/8 mod 29 = -3 * 11 mod 29 = -33 mod 29 = 26 |
| 67 | +# S(31) = -3/8 mod 31 = -3 * 27 mod 31 = -81 mod 31 = 13 |
| 68 | +# S(37) = -3/8 mod 37 = -3 * 28 mod 37 = -84 mod 37 = 9 |
| 69 | + |
| 70 | + |
| 71 | + |
| 72 | +class Problem381: |
| 73 | + def __init__(self): |
| 74 | + pass |
| 75 | + |
| 76 | + @timeit |
| 77 | + def solve(self, n): |
| 78 | + primes = primes_upto(n) |
| 79 | + total = 0 |
| 80 | + for p in primes[2:]: |
| 81 | + total += self.S(int(p)) |
| 82 | + return total |
| 83 | + |
| 84 | + @staticmethod |
| 85 | + def S(p): |
| 86 | + return (pow(-8, -1, p) * 3) % p |
| 87 | + |
| 88 | + |
| 89 | +class Solution381(unittest.TestCase): |
| 90 | + def setUp(self): |
| 91 | + self.problem = Problem381() |
| 92 | + |
| 93 | + def test_small_n(self): |
| 94 | + self.assertEqual(480, self.problem.solve(n=100)) |
| 95 | + |
| 96 | + def test_solution(self): |
| 97 | + self.assertEqual(139602943319822, self.problem.solve(n=int(pow(10, 8)))) |
| 98 | + |
| 99 | + |
| 100 | +if __name__ == '__main__': |
| 101 | + unittest.main() |
0 commit comments