[codeforces] 1900D. Small GCD

starbow·2024년 5월 23일

PS/CP

목록 보기
4/25

문제 링크

크기가 nn인 수열 aa에 대하여 i=1nj=i+1nk=j+1nf(ai,aj,ak)\displaystyle\sum_{i=1}^{n}{\displaystyle\sum_{j=i+1}^{n}{\displaystyle\sum_{k=j+1}^{n}{f(a_{i}, a_{j}, a_{k})}}}를 구하는 문제입니다. f(x,y,z)f(x, y, z)x,y,zx, y, z중에서 가장 작은 두 값의 최대공약수입니다.

먼저 이 식을 변형 시켜봅시다. 어차피 세 수 중 가장 작은 두 값의 최대공약수를 구하므로 aa를 오름차순으로 정렬한 수열을 bb라고 하면

i=1nj=i+1nk=j+1nf(ai,aj,ak)=i=1n1j=i+1n1gcd(bi,bj)(nj)=k=2n1i=1kj=i+1kgcd(bi,bj)\begin{aligned} &\displaystyle\sum_{i=1}^{n}{\displaystyle\sum_{j=i+1}^{n}{\displaystyle\sum_{k=j+1}^{n}{f(a_{i}, a_{j}, a_{k})}}} \\ = &\displaystyle\sum_{i=1}^{n-1}{\displaystyle\sum_{j=i+1}^{n-1}{\gcd(b_{i}, b_{j}) \cdot (n-j)}} \\ = &\displaystyle\sum_{k=2}^{n-1}{\displaystyle\sum_{i=1}^{k}{\displaystyle\sum_{j=i+1}^{k}{\gcd(b_{i}, b_{j})}}} \end{aligned}

가 됩니다.

Sa=k=2ai=1kj=i+1kgcd(bi,bj)  (2an1)S_{a} = \displaystyle\sum_{k=2}^{a}{\displaystyle\sum_{i=1}^{k}{\displaystyle\sum_{j=i+1}^{k}{\gcd(b_{i}, b_{j})}}} \;\, (2 \leq a \leq n-1)라고 한다면 SaSa1=i=1aj=i+1agcd(bi,bj)S_{a}-S_{a-1} = \displaystyle\sum_{i=1}^{a}{\displaystyle\sum_{j=i+1}^{a}{\gcd(b_{i}, b_{j})}}가 되고 Ta=SaSa1T_{a} = S_{a}-S_{a-1}이라고 하면 TaTa1=i=1a1gcd(bi,ba)T_{a}-T_{a-1} = \displaystyle\sum_{i=1}^{a-1}{\gcd(b_{i}, b_{a})}이 됩니다. 즉, 어떻게든 i=1a1gcd(bi,ba)\displaystyle\sum_{i=1}^{a-1}{\gcd(b_{i}, b_{a})}를 계산하면 TT의 다음 항을 구할 수 있고 또한, SS의 다음항도 구할 수 있게 됩니다.

i=1a1gcd(bi,ba)\displaystyle\sum_{i=1}^{a-1}{\gcd(b_{i}, b_{a})}는 아래와 같은 과정으로 계산합니다.
1. 이전부터 b1,...,ba1b_{1}, ..., b_{a-1}의 약수들을 카운트합니다.
2. bab_{a}의 약수들을 큰 수 부터 작은 수 순으로 탐색합니다. 이 때, 아래 과정을 반복합니다.
\quad 2-1. 1. 에서 dd가 카운트된 횟수를 cntcnt라고 하면 cntdcnt \cdot d를 더합니다. gcd(bi,ba)=d\gcd(b_{i}, b_{a}) = dii의 갯수가 cntcnt임을 의미하기 때문입니다. 그리고 1. 에서 카운트한 값들 중 dd의 약수에 해당하는 카운트 값들을 cntcnt만큼 빼줍니다.

이렇게하면 다음 TaTa1T_{a}-T_{a-1}를 구할 수 있고 위에서 설명했듯이 SS의 다음항 또한 구할 수 있습니다.

지금까지 설명한 방법의 시간복잡도는 O(n(max(a)+2835))O(n \cdot (\sqrt{\max(a)} + 2835))입니다. 사실 이 시간복잡도만 놓고 봤을때는 2초가 되려나 싶었는데 390ms로 AC를 받았습니다. 코포는 AC를 받으면 테케를 공개해줘서 확인해봤는데 더 강한 데이터가 있는것 같긴하지만 그게 들어간다고 해도 제 답안이 TLE를 받을 것 같지는 않았습니다. 시간복잡도를 계산할 때 무언가 누락됐거나 딱히 무거운 연산이 없기도 해서 돌아가는 것 같기도 한데... 나중에 조금 더 살펴봐야겠습니다.

profile
🎈 Journey of problem solving

0개의 댓글