행렬 A^B를 구하는 문제입니다. 두 가지만 알면 쉽게 풀 수 있습니다.

1000으로 나눈 나머지를 출력하라고 되어 있으니 제곱할 때마다 mod 연산을 해주면 되고, B의 값이 최대 1000억이기 때문에 그냥 제곱하면 안됩니다..

분할정복으로 a^n을 O(log n)에 계산할 수 있는 방법이 있으니 그런 식으로 계산해야 하구요 1000억이라고 해봐야 log_2(1000억) = 36...이니 얼마 안됩니다.

참고로 결과값 배열을 구할때 항등원(기약행렬)부터 곱해나가기 시작해야 합니다.

#include <cassert>
#include <iostream>
#include <vector>
using namespace std;

using ll = long long;
using matrix = vector<vector<int>>;
const int MOD = 1000;

matrix mul(matrix a, matrix b) {
	assert(a[0].size() == b.size());

	// (l행 m열) * (m행 n열) = (l행 n열)
	const auto rows = a.size(),
		cols = b[0].size(),
		m = a[0].size();

	matrix res(rows, vector<int>(cols));
	for (int i = 0; i < rows; ++i) {
		for (int j = 0; j < cols; ++j) {
			for (int k = 0; k < m; ++k) {
				res[i][j] += a[i][k] * b[k][j];
			}
			res[i][j] %= MOD;
		}
	}

	return res;
}

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

#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif	// ONLINE_JUDGE
	
	ll n, b;
	cin >> n >> b;

	matrix a(n, vector<int>(n));
	matrix res = a;
	for (int i = 0; i < n; ++i)
		for (int j = 0; j < n; ++j)
			cin >> a[i][j];

	for (int i = 0; i < n; ++i)
		res[i][i] = 1;

	while (b > 0) {
		if (b & 1) {
			res = mul(res, a);
		}

		a = mul(a, a);
		b >>= 1;
	}

	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < n; ++j) {
			if (j) cout << ' ';
			cout << res[i][j];
		}
		cout << '\n';
	}

	return 0;
}
반응형

'Online Judge > 백준' 카테고리의 다른 글

[백준][C++] 1024: 수열의 합  (0) 2021.03.19
[백준][C++] 2417: 정수 제곱근  (0) 2020.10.30
[백준][C++] 10830: 행렬 제곱  (0) 2020.10.30
[백준][C++] 1322: X와 K  (0) 2020.10.29
[백준][C++] 14719: 빗물  (2) 2020.09.19
[백준][C++] 17419: 비트가 넘쳐흘러  (0) 2020.08.30