백준 10830번 : 행렬 제곱[C#]
2026. 3. 15. 12:08ㆍCS/알고리즘
1. B가 100,000,000,000 까지 될 수 있어서 제곱을 정직하게 시행하면 시간초과가 날 것이다.
> 분할정복의 거듭제곱을 이용해야하고,
2. 행렬을 100,000,000,000번 제곱하는 동안 원소가 굉장히 커진다.
> 마지막에 1000으로 나머지 연산을 한다는 조건을 이용하여 나머지 연산의 분배법칙을 적용할 수 있다.
3. 분할정복의 거듭제곱을 행렬에도 적용하고, 연산마다 1000으로 나머지 연산을 시행하여 숫자가 과도하게 커지지 않도록 조절한다.
분할정복의 거듭제곱과 나머지연산의 분배법칙은 아래 링크에서 다루고 있다.
https://growup.tistory.com/210
알고리즘 문제 관련 수학 모음
1) 2026-03-14, 1 ~ 4번 추가 1. 나머지 연산 분배법칙 https://www.acmicpc.net/problem/1629 2. 페르마의 소정리 및 응용 ( 분수 ↔ 지수 )전환 시 활용 가능 https://www.acmicpc.net/problem/11401 3. 분할정복을 사용한 효
growup.tistory.com
using System;
class Program
{
static int P = 1000;
static int N;
static void Main()
{
string[] input = Console.ReadLine().Split();
N = int.Parse(input[0]);
long B = long.Parse(input[1]);
int[,] mat = new int[N, N];
int[,] res = new int[N, N];
for (int r = 0; r < N; r++)
{
input = Console.ReadLine().Split();
for (int c = 0; c < N; c++)
{
mat[r,c] = int.Parse(input[c]); // 입력받을 때 1000으로 먼저 나누기
// B= 1 일 때 나머지 연산을 하지 않고 바로 출력하는데, 원소값이 1000인 경우 나머지 연산을 하지 않으면 틀린다. 이 경우를 대비하기 위해 입력받을 때 한 번 나머지연산을 한다.
}
res[r,r] = 1; // 단위행렬로 초기화
}
while(B != 0)
{
if(B%2 == 1) res = Multiply(res,mat);
mat = Multiply(mat,mat);
B/= 2;
}
for (int r = 0; r < N; r++)
{
for (int c = 0; c < N; c++)
{
Console.Write("{0} ", res[r, c]);
}
Console.WriteLine();
}
}
static int[,] Multiply(int[,] mat1, int[,] mat2) // 두 행렬의 곱
{
int[,] res = new int[N,N];
for(int r=0; r<N; r++)
{
for(int c=0; c<N; c++)
{
int n = 0;
for(int i=0; i<N; i++)
{
n += (mat1[r,i]*mat2[i,c])%P;
}
res[r,c] = n%P;
}
}
return res;
}
}'CS > 알고리즘' 카테고리의 다른 글
| 백준 11444번 : 피보나치 수 6[C#] (0) | 2026.03.16 |
|---|---|
| 백준 11401번 : 이항계수 [C#] (0) | 2026.03.14 |
| 알고리즘 문제 관련 수학 모음 (0) | 2026.03.14 |
| 백준 25682번 : 체스판 다시 칠하기 2[C#] (0) | 2026.03.11 |
| 백준 10986번 : 나머지 합 [C#] (0) | 2026.03.09 |