77 lines
1.8 KiB
Python
77 lines
1.8 KiB
Python
"""
|
|
We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once.
|
|
For example, 2143 is a 4-digit pandigital and is also prime.
|
|
|
|
What is the largest n-digit pandigital prime that exists?
|
|
"""
|
|
|
|
import random
|
|
import time
|
|
from functools import lru_cache
|
|
from itertools import permutations
|
|
|
|
|
|
def timer(func):
|
|
def wrapper(*args, **kwargs):
|
|
start_time = time.perf_counter()
|
|
result = func(*args, **kwargs)
|
|
end_time = time.perf_counter()
|
|
print(f"Execution time: {end_time - start_time} seconds")
|
|
return result
|
|
|
|
return wrapper
|
|
|
|
|
|
def miller_rabin_test(n: int, k: int = 10) -> bool:
|
|
if n < 2:
|
|
return False
|
|
if n == 2 or n == 3:
|
|
return True
|
|
if n % 2 == 0 or n % 3 == 0:
|
|
return False
|
|
r, s = 0, n - 1
|
|
while s % 2 == 0:
|
|
r += 1
|
|
s //= 2
|
|
for _ in range(k):
|
|
a = random.randrange(2, n - 1)
|
|
x = pow(a, s, n)
|
|
if x == 1 or x == n - 1:
|
|
continue
|
|
for _ in range(r - 1):
|
|
x = pow(x, 2, n)
|
|
if x == n - 1:
|
|
break
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
|
|
@lru_cache(maxsize=128)
|
|
def is_even_or_five_ending(num: int) -> bool:
|
|
"""快速检查是否为偶数或以5结尾"""
|
|
return num % 2 == 0 or num % 5 == 0
|
|
|
|
|
|
@timer
|
|
def main() -> None:
|
|
str_nums = "987654321"
|
|
stop = False
|
|
for i in range(9, 0, -1):
|
|
if sum(int(digit) for digit in str_nums[-i:]) % 3 == 0:
|
|
continue
|
|
for perm in permutations(str_nums[-i:], i):
|
|
num = int("".join(perm))
|
|
if is_even_or_five_ending(num):
|
|
continue
|
|
if miller_rabin_test(num):
|
|
print(num)
|
|
stop = True
|
|
break
|
|
if stop:
|
|
break
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|