10830번: 행렬 제곱
크기가 N*N인 행렬 A가 주어진다. 이때, A의 B제곱을 구하는 프로그램을 작성하시오. 수가 매우 커질 수 있으니, A^B의 각 원소를 1,000으로 나눈 나머지를 출력한다.
www.acmicpc.net
- B가 굉장히 큰 값이기 때문에, 전체를 다 곱해줄 수는 없다.
- B를 이진수로 생각하여, 0승부터 k승까지 주어진 행렬을 제곱해나가면서 확인할 수 있다.
- 만약 1인 비트가 있다면 정답 행렬에 현재 승수의 행렬을 곱해주면 logN 번만의 행렬곱에 구할 수 있다.
N, B = map(int, input().split())
mat = [list(map(int, input().split())) for i in range(N)]
answer = [[1 if i==j else 0 for j in range(N)] for i in range(N)] # 업데이트 될 정답행렬, I 로 시작
def matmul(a, b): # 행렬곱 함수, 모듈러 연산이 적용돼있음
return [[sum(r) % 1000 for r in zip(*[[(arow[i] * e) % 1000 for e in b[i]] for i in range(N)])] for arow in a]
for flag in map(int, str(bin(B))[-1:1:-1]): # B 를 2진수로 바꿔서 mat 을 제곱해주며 필요한 승수마다 answer 에 곱해줌
if flag:
answer = matmul(answer, mat)
mat = matmul(mat, mat) # mat 은 계속 제곱됨
for row in answer:
print(*row)
'PS > BOJ' 카테고리의 다른 글
[백준] 1080 : 행렬 (0) | 2021.05.05 |
---|---|
[백준] 11664 : 선분과 점 (0) | 2021.05.04 |
[백준] 16928 : 뱀과 사다리 게임 (0) | 2021.05.01 |
[백준] 11659 : 구간 합 구하기 4 (0) | 2021.04.30 |
[백준] 1707 : 이분 그래프 (0) | 2021.04.13 |