Baekjoon Review
[Gold 4] 10830 행렬 제곱
hanseongbugi
2024. 9. 14. 17:27
https://www.acmicpc.net/problem/10830
지수가 int 값 범위를 초과할 수 있으므로 거듭 제곱을 하는 과정에서 시간 초과가 발생할 수 있다.
이는 지수 법칙과 나머지 연산의 성질을 이용해서 해결할 수 있다.
지수법칙
a^(n + m) = a^n + a^m
모듈러 성질
(a x b) mod c = (a mod c x b mod c) mod c
(a * b) % c = (a % c * b % c) % c
지수 법칙 이용 방법
짝수인 경우
a^8 = a^4 * a^4
= (a^2 * a^2) * (a^2 * a^2)
= ((a^1 * a^1) * (a^1 * a^1)) * ((a^1 * a^1) * (a^1 * a^1))
홀수인 경우
a^9 = a^4 * a^4 * a
= (a^2 * a^2) * (a^2 * a^2) * a
= ((a^1 * a^1) * (a^1 * a^1)) * ((a^1 * a^1) * (a^1 * a^1)) * a
위와 같이 지수를 반으로 나누면서 활용할 수 있다.
지수를 2로 나누다보면 지수가 짝수로 나오다가 1로 나오게 된다.
#include <iostream>
using namespace std;
long long N, B;
long long matrix[5][5];
long long answer[5][5];
long long sum[5][5];
void calc(long long x[5][5], long long y[5][5]){
for(int i = 0;i<N;i++){
for(int j = 0;j<N;j++){
sum[i][j] = 0;
for(int k = 0;k<N;k++){
sum[i][j] += x[i][k] * y[k][j];
}
sum[i][j] %= 1000;
}
}
for(int i = 0;i<N;i++)
for(int j = 0;j<N;j++)
x[i][j] = sum[i][j];
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>N>>B;
for(int i = 0;i<N;i++){
for(int j = 0;j<N;j++)
cin>>matrix[i][j];
answer[i][i] = 1; // 단위 행렬
}
while(B > 0){ // 5 -> 2 -> 1
if(B % 2 == 1){
// 홀수 인 경우 정답행렬에 A행렬 곱
calc(answer, matrix);
}
// 지수법칙 사용
calc(matrix, matrix);
B /= 2;
}
for(int i = 0;i<N;i++){
for(int j = 0;j<N;j++)
cout<<answer[i][j]<<' ';
cout<<'\n';
}
}