티스토리 뷰
의 값을 구하기 위한 거듭제곱 연산을 구현한다고 하자.
naive한 방법은 for문을 돌면서 N을 K번 곱해주면 된다. 이럴 경우 시간복잡도는 O(K)이다.
1 2 3 | int result=1; for(int i=1 ; i<=k ; i++) result=result*n; | cs |
하지만 O(K)보다 빠른 O(logK)만에 구하는 방법도 존재한다. 바로 N^2을 이용하여 N^4를 구하고, 또 이를 이용하여 N^8을 구하는 방식 이용해서 말이다.
1 2 3 4 5 6 7 8 9 10 11 12 | typedef long long ll; ll my_pow(ll n,ll k){ ll result=1; while(k){ if(k&1) //k값이 홀수일 때만 계산 result=result*n; k/=2; n=n*n; } return result; } | cs |
나머지를 취해야할 때는 이렇게 하면 된다.
1 2 3 4 5 6 7 8 9 10 11 | typedef long long ll; ll my_pow(ll n,ll k){ ll result=1; while(k){ if(k&1) //k값이 홀수일 때만 계산 result=(result*n)%MOD; k/=2; n=(n*n)%mod; } return result; } | cs |
또한 (나머지 거듭제곱)-(나머지 거듭제곱)을 필요로 하는 경우가 있다. 이때 주의해야할 점은 나머지를 취했기 때문에 음수가 나올 수도 있다는 점이다. 이를 방지하기 위해서는 마지막에 MOD를 더해주고, 다시 MOD를 나머지 취해주어야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | typedef long long ll; ll my_pow(ll n,ll k){ ll result=1; while(k){ if(k&1) //k값이 홀수일 때만 계산 result=(result*n)%MOD; k/=2; n=(n*n)%mod; } return result; } int main(){ int ans=0; ans-=my_pow(N,K); ans=ans+MOD; ans=ans%MOD; . . . } | cs |
'Reference' 카테고리의 다른 글
array에서 shift (0) | 2022.02.11 |
---|---|
트리에서 노드 a가 b의 조상인지 확인하는 법 (0) | 2019.12.24 |
포함-배제의 원리 (0) | 2019.10.29 |
확장 유클리드 알고리즘, 페르마 소정리, 중국인 나머지 정리 (0) | 2019.10.24 |
소인수분해 문제 (0) | 2019.04.17 |
댓글