조합을 그대로 구하는 것이 아니라 끝에 붙은 의 개수를 구하는 것에 주목합니다. 을 소인수분해하면 어떻게 될 지 모르겠지만 꼴로 생각할 수 있고, 이 때 가 뒤에 붙은 의 개수가 됩니다. 을 만들기 위해서는 와 가 하나씩 필요하므로 소인수분해했을 때 와 의 개수 중 작은 것이 문제의 정답이 됩니다. 소인수분해의 시간 복잡도는 단순하게 구현하면 이지만 의 크기를 봐서는 으로도 답이 없습니다
은 이고, 이는 연속된 수들의 곱입니다. 만약 을 소인수분해했을 때 의 개수를 알고 싶다면 부터 까지 수 중에서 로 나누어 떨어지는 수의 개수를 구하면 될 것 같다고 생각할 수도 있습니다. 이것은 로 쉽게 구할 수 있습니다. 그러나 이것은 답이 아닙니다. 도 로 나누어지지만 이런 방식으로 하면 개씩밖에 세 주지 않기 때문입니다. 의 거듭제곱으로 나누어떨어지는 수들이 문제입니다. 그러므로 모든 의 거듭제곱에 대해서 를 계산해서 답을 구하고 도 마찬가지로 구합니다. 만 되어도 을 넘기 때문에 매우 빠를것이라 예상할 수 있습니다.
에 포함된 의 개수 라고 정의하면
= 임을 알 수 있습니다.
# 정수 x!을 소인수분해했을 때 2의 개수와 5의 개수 반환
def f(x):
p = [0, 0]
a, b = 2, 5
while a <= x:
p[0] += x // a
a *= 2
while b <= x:
p[1] += x // b
b *= 5
return p
n, m = map(int, input().split())
a = f(n)
b = f(n - m)
c = f(m)
a[0] -= b[0]
a[0] -= c[0]
a[1] -= b[1]
a[1] -= c[1]
print(min(a))
의 시간 복잡도는 가 지수적으로 증가하므로 이다
2000000000 1000000007
->10