Week 01 ~ 04 : 알고리즘 문제 풀이

파이썬 백준 10830 행렬 제곱

정글러 2021. 11. 12. 19:01
n, b = map(int, input().split())
A = []
for i in range(n) :
    A.append(list(map(int, input().split())))

I = [[0 for i in range(n)] for j in range(n)]
for i in range(n) :
    I[i][i] = 1
   
def mult(A, B) :
    C = [[0 for i in range(n)] for j in range(n)]
    for i in range(n) :
        for j in range(n) :
            sum = 0
            for x in range(n) :
                sum = sum + A[i][x] * B[x][j]
            C[i][j] = sum % 1000
    return C

powerlist = [0 for i in range(37)]
for i in range(n) :
    for j in range(n) :
        A[i][j] = A[i][j] % 1000
powerlist[0] = A
for i in range(1, 37) :
    powerlist[i] = mult(powerlist[i-1], powerlist[i-1])

bilist = [0 for i in range(37)]
for i in range(36, -1, -1) :
    bilist[i] = b // pow(2, i)
    b = b - bilist[i] * pow(2, i)

ans = [[] for i in range(n)]
if bilist[0] == 1 :
    for i in range(n) :
        ans[i] = powerlist[0][i][:]
else :
    for i in range(n) :
        ans[i] = I[i][:]
for i in range(1, 37) :
    if bilist[i] == 1 :
        ans = mult(ans, powerlist[i])
for i in range(n) :
    for j in range(n-1) :
        print(ans[i][j] , end = ' ')
    print(ans[i][-1])

행렬의 곱셈도 정수의 곱셈처럼 결합법칙이 성립한다.

즉, 행렬곱함수나 항등원같이 필요한 것을 만들어준다면 백준 1629번 곱셈과 똑같은 방법으로 풀 수 있다.

 

행렬을 곱해 mod1000을 남기는 함수 mult를 정의하고, 항등원 I를 만든다.

이후 1629에서 쓴 코드를 자료형에 맞게 갖다 쓰면 끝