-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpe00302 - Strong Achilles Numbers.py
124 lines (105 loc) · 3.16 KB
/
pe00302 - Strong Achilles Numbers.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jun 3 15:39:03 2022
@author: igorvanloo
"""
'''
Project Euler Problem 302
1) largest prime is < 10^6
2) gcd(exponents of n) = 1
1) Note that if the largets factor p of n has exponent 2, this means φ(n) =...p*(p-1) => there will only be one
p in the factorisation of φ(n) and therefore it cannot be an Achilles number,
this also also means we need to consider primes <= 10^6 because the largest prime must have atleast a power of 3
2) if the gcd(exponents of n) = d ≠ 1 then we have n = q^d and therefore it is a perfect power
Just need to efficiently find all candidate numbers
Anwser:
'''
import time, math
start_time = time.time()
def list_primality(n):
result = [True] * (n + 1)
result[0] = result[1] = False
for i in range(int(math.sqrt(n)) + 1):
if result[i]:
for j in range(2 * i, len(result), i):
result[j] = False
return result
def list_primes(n):
return [i for (i, isprime) in enumerate(list_primality(n)) if isprime]
def prime_factors(n):
factors = {}
d = 2
while n > 1:
while n % d == 0:
if d in factors:
factors[d] += 1
else:
factors[d] = 1
n /= d
d = d + 1
if d * d > n:
if n > 1:
n = int(n)
if d in factors:
factors[n] += 1
else:
factors[n] = 1
break
return factors
def phi2(pf):
new_pf = {}
for p in pf:
if p != "prod":
new_pf[p] = (pf[p] - 1)
for q, e in prime_factors(p - 1).items():
if q in new_pf:
new_pf[q] += e
else:
new_pf[q] = e
return new_pf
def condition_checker(curr):
alist = [curr[y] for y in curr if y != "prod"]
if len(alist) == 1:
return 0
t = alist[0]
for x in range(len(alist)):
curr = alist[x]
if curr < 2:
return 0
t = math.gcd(t, curr)
return t
def compute(limit):
primes = list_primes(int(limit**(1/3)))
options1 = set([])
candidates = set([])
for a in range(1, len(primes)):
p = primes[a]
for b in range(a):
q = primes[b]
t = p*p*p*q*q
if t < limit:
options1.add(t)
candidates.add(t)
print("options1 ready")
count = 0
while len(options1) != 0:
curr = options1.pop()
for x in primes:
t = curr*x
if t < limit:
candidates.add(t)
options1.add(t)
print("candidates ready")
print("--- %s seconds ---" % (time.time() - start_time))
for x in candidates:
pf = prime_factors(x)
if condition_checker(pf) == 1:
phi_pf = phi2(pf)
if condition_checker(phi_pf) == 1:
#print(x)
count += 1
return count
if __name__ == "__main__":
print(compute(10**8))
print("--- %s seconds ---" % (time.time() - start_time))