구현 방식
- 행렬
mat
의 4 제곱은 mat^4 = mat^2 * mat^2 = mat * mat * mat * mat
와 같다.
- 행렬
mat
의 5 제곱은 mat^4 = mat^2 * mat^2 * mat = mat * mat * mat * mat * mat
와 같다.
- 즉 짝수 제곱은
mat^N = mat^(N/2) * mat^(N/2)
이며, 홀수 제곱은 mat^N = mat^(N/2) * mat^(N/2) * mat
로 나타낼 수 있다.
- 분할 정복 및 이전에 방문한 내용 기록을 통해서 풀도록한다.
- 행렬 곱을 편하게 하기위해
* operator
연산을 할 수 있는 Matrix
클래스를 만들었다.
코드
const int MATMAXSIZE = 5;
const int MOD = 1000;
map<long long, Matrix> dict;
class Matrix
{
public:
Matrix() { }
Matrix(int N) : Size(N) { }
public:
Matrix operator*(const Matrix& m)
{
Matrix result(Size);
for (int i = 0; i < Size; i++)
{
for (int j = 0; j < Size; j++)
{
for (int k = 0; k < Size; k++)
result.mat[i][j] += this->mat[i][k] * m.mat[k][j];
result.mat[i][j] %= 1000;
}
}
return result;
}
static void print(Matrix m)
{
for (int i = 0; i < m.Size; i++)
{
for (int j = 0; j < m.Size; j++)
{
cout << m.mat[i][j] << " ";
}
cout << "\n";
}
}
public:
int Size;
int mat[MATMAXSIZE][MATMAXSIZE] = {};
};
int main()
{
int N;
long long B;
cin >> N >> B;
Matrix Mat(N);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++)
{
cin >> Mat.mat[i][j];
Mat.mat[i][j] %= 1000;
}
solution(Mat, B);
}
void solution(Matrix& Mat,long long B)
{
dict[1] = Mat;
Matrix result = calcExponent(B);
Matrix::print(result);
}
Matrix calcExponent(long long expo)
{
if (dict.find(expo) != dict.end())
return dict[expo];
// 홀 수
if (expo % 2 == 1)
{
dict[expo] = calcExponent(expo / 2) * calcExponent(expo / 2)* calcExponent(1);
return dict[expo];
}
// 짝 수
else
{
dict[expo] = calcExponent(expo / 2) * calcExponent(expo / 2);
return dict[expo];
}
}