N*N 크기의 행렬 A, A의 B제곱을 구하라. 수가 매우 커질 수 있으니 A^B의 각 원소를 1,000으로 나눈 나머지를 출력.
2≤N≤5, 1≤B≤100,000,000,000
B가 아주 크다. 단순한 방법으로는 안된다.
행렬 A의 B제곱은 A의 B-1 제곱에 A를 곱한 것이다. 팩토리얼과 유사하다. 그런데 B가 최대이면 단순하게 순회를 1번만 돌아도 시간초과이다.
B가 100만이라고 해보자 A^100만 = (A^50만)^2
$$ A^B = {A^{(B/2)}}^2 $$
이러면 B가 1천억이라 하더라도 500억 → 250억 → 125억 이렇게 logN으로 감소시킬 수 있다.
그런데 B가 홀수냐 짝수냐에 따라서 처리를 좀 달리해야 한다. B가 짝수라면 그냥 해도 되지만 B가 홀수라면 1일 빼서 짝수로 만든 다음 해당 과정을 처리하고 마지막에 하나를 다시 곱해준다.
필요한 연산들은 다음과 같다.
- 행렬의 곱셈
- 거듭제곱의 재귀
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[][] matrix;
static long B;
static final int MOD = 1_000;
static FastReader scan = new FastReader();
static void input() {
N = scan.nextInt();
B = scan.nextLong();
matrix = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
matrix[i][j] = scan.nextInt() % MOD;
}
}
}
static int[][] multiply(int[][] A, int[][] B) {
int[][] C = new int[N][N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) {
C[i][j] = (C[i][j] + (A[i][k] * B[k][j]) % MOD) % MOD;
}
}
}
return C;
}
static int[][] power(int[][] A, long B) {
if (B == 1) {
return A;
}
int[][] tmp = power(A, B / 2);
tmp = multiply(tmp, tmp);
if (B % 2 == 1) {
tmp = multiply(tmp, matrix);
}
return tmp;
}
static void solve() {
int[][] result = power(matrix, B);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
System.out.print(result[i][j] + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
input();
solve();
}
static class FastReader {
BufferedReader br;
StringTokenizer st;
public FastReader() {
br = new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while (st == null || !st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
long nextLong() {
return Long.parseLong(next());
}
}
}
'Algorithm > BOJ' 카테고리의 다른 글
BOJ 2933 - 미네랄 (0) | 2024.11.05 |
---|---|
BOJ 15591 - MooTube (Silver) (0) | 2024.10.31 |
BOJ 12865 - 평범한 배낭 (0) | 2024.10.31 |
BOJ 15989 - 1,2,3 더하기 4 (0) | 2024.10.26 |
BOJ 1528 - 금민수의 합 (0) | 2024.10.26 |