알고리즘 모음(C++)

백준 10830 - 행렬 제곱(C++) 본문

백준

백준 10830 - 행렬 제곱(C++)

공대생의 잡다한 사전 2022. 2. 20. 15:30

문제 링크입니다. https://www.acmicpc.net/problem/10830

 

10830번: 행렬 제곱

크기가 N*N인 행렬 A가 주어진다. 이때, A의 B제곱을 구하는 프로그램을 작성하시오. 수가 매우 커질 수 있으니, A^B의 각 원소를 1,000으로 나눈 나머지를 출력한다.

www.acmicpc.net

행렬 제곱을 분할 정복을 통해 푸는 문제입니다.

이 문제를 풀기 위해서는 행렬의 제곱을 할 수 있어야 합니다.

행렬 제곱이 어떻게 계산되는지 2 * 2 / 3 * 3 행렬을 통해 확인해보겠습니다.

2 * 2 / 3 * 3 행렬의 곱셈을 통해, 앞 행렬은 [X][Y] 중 X부분이 바뀌고, 뒤 행렬은 Y부분이 바뀌는 것을 알 수 있습니다.

이를 통해 행렬의 곱셈을 구현할 수 있습니다.

matrix multi(matrix a, matrix b) {
	matrix ans;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			int sum = 0;
			for (int k = 0; k < N; k++) {
				sum += a.Data[i][k] * b.Data[k][j];
				sum %= 1000;
			}
			ans.Data[i][j] = sum;
		}
	}
	return ans;
}

 

이제 행렬을 직접 제곱하기만 하면 되는데, B의 범위가 최대 1000억입니다. 

for문을 통해 제곱을 만들면, 시간 초과가 생기기에 다른 방법이 필요합니다.

이때 사용하는 방법이 분할 정복입니다.

N값을 통해 나눠주면서 곱해주면 빠르게 계산할 수 있습니다.

 

 

자세한 것은 코드를 참고해주세요

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstdio>
#include <string>
#include <deque>
#include <stack>

using namespace std;

int N;
long long int B;
typedef struct matrix {
	int Data[5][5];
}matrix;
matrix Base;


matrix multi(matrix a, matrix b) {
	matrix ans;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			int sum = 0;
			for (int k = 0; k < N; k++) {
				sum += a.Data[i][k] * b.Data[k][j];
				sum %= 1000;
			}
			ans.Data[i][j] = sum;
		}
	}
	return ans;
}

matrix Multiple(matrix x, long long int y) {
	if (y > 1) {
		x = Multiple(x, y / 2);
		x = multi(x, x);
		if (y % 2 == 1) {
			x = multi(x, Base);
		}
	}
	return x;
}

void solve() {
	matrix arr;
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> arr.Data[i][j];
			arr.Data[i][j] %= 1000;
		}
	}
	Base = arr;
	arr = Multiple(arr, B);
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cout << arr.Data[i][j] << " ";
		}
		cout << "\n";
	}
}

int main() {
	cin.tie(0);
	cout.tie(0);
	cin >> N >> B;
	solve();
	return 0;
}

 

 

질문 및 조언 댓글 남겨주세요

'백준' 카테고리의 다른 글

백준 2108 - 통계학(C++)  (0) 2022.02.21
백준 12851 - 숨바꼭질 2(C++)  (0) 2022.02.20
백준 15666 - N과 M(12)(C++)  (0) 2022.02.20
백준 15663 - N과 M(9)(C++)  (0) 2022.02.20
백준 15657 - N과 M(8)(C++)  (0) 2022.02.20