문제 링크
1900이라고 방심했다가 크게 데인 문제입니다... 생각보다 생각하기 어렵더라고요... 더 열심히 연습해야겠습니다.
1이상 109이하의 정수들로 이루어진 길이가 n인 배열 a가 있습니다. a의 부분 배열 중에서 배열의 모든 요소의 최소공배수가 a의 요소가 아닌 배열 중 최대 길이를 구하는 문제입니다.
케이스를 나눠서 생각해 보겠습니다.
Case 1) lcm(a1,...,an)>an
이건 두말할 필요 없이 n을 출력하면 됩니다.
Case 2) lcm(a1,...,an)=an
우선 부분 배열에는 an이 있으면 안됩니다. an이 들어가는 순간 최소공배수는 바로 an이 되기 때문입니다. 그래서 저희는 an을 제외하고 부분 배열을 만들어야 합니다.
그리고 어떠한 부분 배열을 만들어도 길이가 0이 아니라면 최소공배수는 an의 약수가 됩니다. 즉, 아래 과정을 통해서 부분 배열의 최대 길이를 찾을 수 있습니다.
- ans=0으로 설정합니다. 그리고 an의 약수들을 구합니다.
- an의 약수들을 순회하면서 아래 과정을 반복합니다. (편의상 약수를 d라고 하겠습니다.)
2-1. a1,...,an−1 중에서 ai∣d인 ai들의 최소공배수와 갯수를 구합니다. 편의상 최소공배수를 l, 갯수를 cnt라고 하겠습니다.
2-2. l=d라면 ans=max(ans,cnt)로 업데이트 합니다.
- ans를 출력합니다.
위 풀이의 시간복잡도는 O(n⋅max(ai)31⋅logmax(ai))입니다.
O(max(ai)31)은 ≤109을 만족하는 정수 중에서 약수가 가장 많은 정수의 약수의 갯수를 의미합니다. 시간복잡도를 계산할 때 어떻게 해야할지 몰라서 검색을 해보니 ≤1018에서 약수의 갯수가 최대인 정수의 약수의 갯수를 O(n31)로 생각하면 얼추 맞다고 합니다. 물론 이는 정확한 수학적 근거를 통해서 나온 값이 아닌 실제 계산을 통해서 얻어진 추정값인것 같습니다.
여담으로 약수의 갯수와 관련하여 아래와 같은 성질이 있다고 합니다.
∀ε>0d(n)=o(nε)
d(n)은 n의 약수의 갯수, o(f(n))은 little-o notation입니다.
참고
Divisor function - Wikipedia
Upper bound for number of divisors - Codeforces
1344 maximal divisors - OEIS