Symbol(clack:cancel)
This commit is contained in:
87
solutions/0000_0029/0005.smallestMultiple/eular_5.py
Normal file
87
solutions/0000_0029/0005.smallestMultiple/eular_5.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""
|
||||
2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
|
||||
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
|
||||
"""
|
||||
|
||||
import math
|
||||
import random
|
||||
import time
|
||||
|
||||
|
||||
def timer(func):
|
||||
def wrapper(*args, **kwargs):
|
||||
start_time = time.time()
|
||||
result = func(*args, **kwargs)
|
||||
end_time = time.time()
|
||||
print(f"{func.__name__} took {end_time - start_time:.6f} seconds")
|
||||
return result
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def is_probable_prime(n: int, trials: int = 10) -> bool:
|
||||
"""Miller-Rabin素性测试(快速判断是否为质数)"""
|
||||
if n < 2:
|
||||
return False
|
||||
if n in (2, 3):
|
||||
return True
|
||||
if n % 2 == 0:
|
||||
return False
|
||||
|
||||
# 将 n-1 写成 d * 2^s 的形式
|
||||
d = n - 1
|
||||
s = 0
|
||||
while d % 2 == 0:
|
||||
d //= 2
|
||||
s += 1
|
||||
|
||||
# 测试
|
||||
for _ in range(trials):
|
||||
a = random.randrange(2, n - 1)
|
||||
x = pow(a, d, n)
|
||||
if x == 1 or x == n - 1:
|
||||
continue
|
||||
for _ in range(s - 1):
|
||||
x = pow(x, 2, n)
|
||||
if x == n - 1:
|
||||
break
|
||||
else:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def primes_up_to(n: int) -> list[int]:
|
||||
if n < 2:
|
||||
return []
|
||||
if n == 2:
|
||||
return [2]
|
||||
if n == 3:
|
||||
return [2, 3]
|
||||
|
||||
primes = [2, 3]
|
||||
for i in range(5, n + 1, 2):
|
||||
if is_probable_prime(i):
|
||||
primes.append(i)
|
||||
|
||||
return primes
|
||||
|
||||
|
||||
@timer
|
||||
def smallest_multiple(n: int) -> int:
|
||||
result = 1
|
||||
for p in primes_up_to(n):
|
||||
# 找出最大幂次
|
||||
exp = int(math.log(n, p))
|
||||
result *= p**exp
|
||||
return result
|
||||
|
||||
|
||||
@timer
|
||||
def python_solution(n: int) -> int:
|
||||
ls = list(range(1, n + 1))
|
||||
return math.lcm(*ls)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(smallest_multiple(20))
|
||||
print(python_solution(20))
|
||||
11
solutions/0000_0029/0005.smallestMultiple/readme.md
Normal file
11
solutions/0000_0029/0005.smallestMultiple/readme.md
Normal file
@@ -0,0 +1,11 @@
|
||||
想法来自: [A003418](https://oeis.org/A003418) 。
|
||||
|
||||
对于 [a .. b] 这个连续整数区间,最小的可整除的整数,就是:
|
||||
|
||||
**小于b的所有质数分别小于b的最大幂值的乘积** 。
|
||||
|
||||
计算步骤就是:
|
||||
|
||||
1. 找出不超过 $b$ 的所有质数 ${p}$
|
||||
2. 对每个质数 $p$ ,找出最大指数 $e$ 使得 $p^e \leq b$
|
||||
3. 将所有 $p^e$ 相乘
|
||||
Reference in New Issue
Block a user