BOJ 10830 행렬 제곱

2020. 9. 16. 18:36·알고리즘/BOJ

www.acmicpc.net/problem/10830

 

10830번: 행렬 제곱

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

www.acmicpc.net

분할 정복 연습 문제다.

이 문제를 풀기 전에 

www.acmicpc.net/problem/2740

 

2740번: 행렬 곱셈

첫째 줄에 행렬 A의 크기 N 과 M이 주어진다. 둘째 줄부터 N개의 줄에 행렬 A의 원소 M개가 순서대로 주어진다. 그 다음 줄에는 행렬 B의 크기 M과 K가 주어진다. 이어서 M개의 줄에 행렬 B의 원소 K개

www.acmicpc.net

이 문제를 먼저 풀 줄 알아야 한다.

행렬 a, b가 있다면 a의 행과 b의 열을 같은 인덱스에 각각 곱해서 합친 값이 그 값이다.

이 문제를 풀 때에는 operator * 를 사용해서 pow계산을 하기 편하게 해 줬다.

vii operator* (const vii& a, const vii& b) {
	int sz = a.size();
	vii ret(sz, vi(sz));
	f(i, sz) {
		f(j, sz) {
			f(k, sz) {
				ret[i][j] += a[i][k] * b[k][j];
			}
			ret[i][j] %= 1000;
		}
	}
	return ret;
}

사실 ps를 하면서 이렇게 operator를 사용할 일이 없어서 재밌었다.

행렬 제곱은 행렬 곱셈을 b만큼 해주면 된다. 위 코드의 operator 함수를 구성했다면 나머지는 그냥

pow함수를 O(log N)으로 해주면 된다.

vii power(vii& a, ll b) {
	int sz = a.size();
	vii ret(sz, vi(sz));
	f(i, sz) ret[i][i] = 1; //단위 행렬
	while (b) {
		if (b % 2) ret = ret * a;
		b /= 2;
		a = a * a;
	}
	return ret;
}

 곱셈을 할 때에는 그냥 곱해주면 안 되고 단위행렬을 만들어 주고 거기다 곱해줘야 한다.

 

#include <iostream>
#include <vector>
using namespace std;
using ll = long long;
#define vii vector<vector<ll>>
#define vi vector<ll>
#define f(i,n) for (int i=0;i<n;i++)

vii operator* (const vii& a, const vii& b) {
	int sz = a.size();
	vii ret(sz, vi(sz));
	f(i, sz) {
		f(j, sz) {
			f(k, sz) {
				ret[i][j] += a[i][k] * b[k][j];
			}
			ret[i][j] %= 1000;
		}
	}
	return ret;
}

vii power(vii& a, ll b) {
	int sz = a.size();
	vii ret(sz, vi(sz));
	f(i, sz) ret[i][i] = 1;
	while (b) {
		if (b % 2) ret = ret * a;
		b /= 2;
		a = a * a;
	}
	return ret;
}

int main() {
	ll n, b;
	cin >> n >> b;
	vii ar(n, vi(n));
	f(i, n) f(j, n) cin >> ar[i][j];

	vii ans = power(ar, b);

	f(i, n) {
		f(j, n) {
			cout << ans[i][j] << ' ';
		}
		cout << '\n';
	}
	return 0;
}

분할 정복은 이해가 잘 안 되는 것 같아서 더 풀어봐야겠다.

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

BOJ 1780 종이의 개수  (0) 2020.09.18
BOJ 1992 쿼드트리  (0) 2020.09.18
BOJ 2343 기타 레슨  (0) 2020.09.15
BOJ 2512 예산  (0) 2020.09.14
백준 11401 이항 계수 3  (0) 2020.09.13
'알고리즘/BOJ' 카테고리의 다른 글
  • BOJ 1780 종이의 개수
  • BOJ 1992 쿼드트리
  • BOJ 2343 기타 레슨
  • BOJ 2512 예산
khyu2
khyu2
  • khyu2
    dev log
    khyu2
  • 전체
    오늘
    어제
    • 분류 전체보기
      • 알고리즘
        • BOJ
        • Programmers
        • Algorithm
        • SWEA
      • 개발
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    냅색
    SWEA
    다익스트라
    코딩테스트 연습
    완전 탐색
    프로그래머스
    알고리즘
    이분탐색
    구현
    큐
    BFS
    분할 정복
    dp
    피보나치 수
    우선순위 큐
    이분 탐색
    완전탐색
    소수
    피사노 주기
    행렬 제곱
    크루스칼
    트리
    시뮬레이션
    dfs
    GREEDY
    팰린드롬
    BOJ
    조합
    유니온 파인드
    MST
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
khyu2
BOJ 10830 행렬 제곱
상단으로

티스토리툴바