https://www.acmicpc.net/problem/13171
코드설명
분할 정복을 이용한 거듭제곱(Divide And Conquer) + 수학(Math) + 비트마스킹(BitMask) 을 활용합니다.
단순하게 분할정복을 이용하여 계산을 시도하면 시간초과가 발생합니다.
그 대신에, 빠른 거듭제곱의 합을 활용하여야 합니다. 문제의 지문에 제시된 대로, 지수연산을 활용해야 합니다.
1. 먼저 2^64 번 제곱이 최고의 수이므로, long[] cache = new long[64]로 선언합니다.
이떄 64는 단순히 64가 아니라, 2^64 를 의미하는 것 입니다.
2. 점화식을 활용해 A^1, A^2, A^4, A^8... 을 계산해나갑니다.
이떄 A^1 은 cache[0]
A^2은 cache[1].
A^3 는 Cache[2] 를 의미합니다.
수학적으로 이야기하면 log2(X) = Cache의 Index입니다.
long[] cache = new long[64];
cache[0] = A % MOD;
for(int i=1; i < 64; i++) {
cache[i] = (cache[i-1] * cache[i-1]) % MOD;
}
3. 지수 X와 비트마스킹을 하여 1, 2, 4, 8, 16, 32... 순으로 해당 지수가 이루어져 있는지 확인합니다.
만약 이루어져있다면, 지수법칙에 의하여 서로 곱해주면 답이 됩니다.
long result = 1;
for(int i=63; i>=0; i--) {
if ((X & (1L << i)) != 0) {
result = (result * cache[i] % MOD);
}
}
코드
정답코드입니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
private static int N, M, C, T, K;
private static int answer = 0;
private static int[] arr;
private static long[] cache;
private static StringBuilder sb = new StringBuilder();
private static final int MOD = (int) 1e9 + 7;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
long A = Long.parseLong(st.nextToken());
st = new StringTokenizer(br.readLine());
long X = Long.parseLong(st.nextToken());
long[] cache = new long[64];
cache[0] = A % MOD;
for(int i=1; i < 64; i++) {
cache[i] = (cache[i-1] * cache[i-1]) % MOD;
}
long result = 1;
for(int i=63; i>=0; i--) {
if ((X & (1L << i)) != 0) {
result = (result * cache[i] % MOD);
}
}
System.out.println(result);
}
}
분할정복을 이용해본 코드입니다. 시간초과가 발생합니다. Cache를 적용하지 못하는 이유는 X의 크기가 1<=X<=1e18 이기 떄문입니다. 만약 Cache를 적용할 수 있었다면 너무 많은 메모리가 사용되긴하겠지만 작동은 할 것입니다. (배열 Size는 32비트까지만 가능)
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
private static int N, M, C, T, K;
private static int answer = 0;
private static int[] arr;
private static long[] cache;
private static StringBuilder sb = new StringBuilder();
private static final int MOD = (int) 1e9 + 7;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
Long A = Long.parseLong(st.nextToken());
st = new StringTokenizer(br.readLine());
Long X = Long.parseLong(st.nextToken());
Arrays.fill(cache, -1);
System.out.println(func(A, X) % MOD);
}
public static long func(long A, long X) {
if(X == 1) return A;
if(X % 2 == 1) return (func(A, X-1) * A ) % MOD;
return (func(A, X/2) * func(A, X/2) ) % MOD;
}
}
시간초과 코드 2 입니다.
package Main;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
private static int N, M, C, T, K;
private static int answer = 0;
private static int[] arr;
private static long[] cache = new long[64];
private static StringBuilder sb = new StringBuilder();
private static final int MOD = (int) 1e9 + 7;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
long A = Long.parseLong(st.nextToken());
st = new StringTokenizer(br.readLine());
long X = Long.parseLong(st.nextToken());
Arrays.fill(cache, -1);
long result = 1;
for(int i=63; i>=0; i--) {
if ((X & (1L << i)) != 0) {
result = (result * func(A, 1L << i) ) % MOD;
}
}
System.out.println(result);
}
public static long func(long A, long X) {
if(X == 1) return A;
if(X % 2 == 1) return (func(A, X-1) * A ) % MOD;
return (func(A, X/2) * func(A, X/2) ) % MOD;
}
}
'알고리즘 > BitMasking' 카테고리의 다른 글
[백준] 15787 기차가 어둠을 헤치고 은하수를 - BitMask(비트마스크) JAVA (0) | 2024.09.07 |
---|---|
[백준] 14939 불 끄기 - 비트마스킹(BitMasking) + 그리디(Greedy) + 순서강제하기 JAVA (0) | 2024.05.14 |