알고리즘/BOJ

백준 10830번 행렬 제곱

lheunoia 2021. 1. 18. 14:31

 

 

문제 보러가기 : https://www.acmicpc.net/problem/10830

 

 

 

10830번: 행렬 제곱

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

www.acmicpc.net

 

 

이번 문제는 분할 정복 문제였습니다.

 

 

 

 

《문제 풀이》

 

1. B의 최댓값이 1000억이므로 long long 자료형으로 선언

2. 2차원 벡터의 공간을 N*N 크기로 할당해줌 --> A(N, vector<int>(N)) 

3. 행렬의 곱을 연산하는 부분은 연산자 오버로딩을 통해 구현

     --> matrix operator * (const matrix &a, const matrix &b)

4. A의 B제곱 연산횟수를 최소화하기 위해 분할 정복 이용 ⭐

5. 지수(B)가 홀수인 경우, 결과 행렬에 밑수(A)를 곱해줌

6. 5번에서 밑수를 하나 빼줬으므로, 지수는 짝수로 바꿔주고(exp / 2) 밑수는 제곱해줌 

 

 

 

 

C++ 코드

 

#include <iostream>
#include <vector>

using namespace std;

int N;
typedef long long ll;
typedef vector<vector<int>> matrix;

matrix operator * (const matrix &a, const matrix &b) {
	matrix res(N, vector<int>(N));
	
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			for(int k=0; k<N; k++) {
				res[i][j] += a[i][k] * b[k][j]; 
			}
			res[i][j] %= 1000;
		}
	}
	return res;
}

matrix calc(matrix a, ll exp) {
	matrix res(N, vector<int>(N));
	
	for(int i=0; i<N; i++)
		res[i][i] = 1; // 단위 행렬  
	
	if(exp == 0) 
		return res;
	 	
	if(exp % 2) // 지수가 홀수인 경우 
		res = res * a;
		
	return res * calc(a * a, exp / 2);
} 

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);

	ll B;
	cin>>N>>B;
	
	// N*N 크기의 2차원 벡터  
	matrix A(N, vector<int>(N));
	
	for(int i=0; i<N; i++)
		for(int j=0; j<N; j++)
			cin>>A[i][j];
	
	matrix res = calc(A, B); // 행렬 A의 B제곱   
	
	for(int i=0; i<N; i++) {
		for(int j=0; j<N; j++) {
			cout<<res[i][j]<<" ";
		}
		cout<<"\n";
	}
		
	return 0;
}

 

 

개발 환경: Dev-C++

 

 

baekjoon - 정답 화면

 

 

 

반응형

'알고리즘 > BOJ' 카테고리의 다른 글

백준 11725번 트리의 부모 찾기  (0) 2021.01.19
백준 9663번 N-Queen  (0) 2021.01.18
백준 13549번 숨바꼭질 3  (0) 2021.01.16
백준 12851번 숨바꼭질 2  (0) 2021.01.16
백준 16953번 A → B  (0) 2021.01.16