[BOJ] #10830 ํ–‰๋ ฌ ์ œ๊ณฑ (Python, ๋ถ„ํ• ์ •๋ณต)

    ๋ฐ˜์‘ํ˜•

     

     

    ๐ŸŒฑ ๋ฌธ์ œ

     

     

    ๐ŸŒฑ ํ’€์ด

    ์ด ๋ฌธ์ œ์˜ ๊ด€๊ฑด์€ 100,000,000,000๊นŒ์ง€ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋Š” ๋งค์šฐ ํฐ ์ง€์ˆ˜๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ–‰๋ ฌ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ณฑํ•˜๋Š” ๋Œ€์‹ , ํ–‰๋ ฌ์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ์„ ๋ถ„ํ•  ์ •๋ณต(Divide and Conquer) ๊ธฐ๋ฒ•์œผ๋กœ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค.

     

    1) ์ž…๋ ฅ ๋ฐ›๊ธฐ

    N, B = map(int, input().split())
    matrix = []
    
    for _ in range(N):
        matrix.append(list(map(int, input().split())))

     

    2) ํ–‰๋ ฌ ์ œ๊ณฑ์„ ๊ตฌํ•˜๋Š” ํ•จ์ˆ˜(Divide and Conquer)

    def pow_matrix(matrix, B):
        """
        ํ–‰๋ ฌ matrix๋ฅผ B ์ œ๊ณฑํ•˜๋Š” ํ•จ์ˆ˜
        """
        if B == 1:
            return [[element % 1000 for element in row] for row in matrix]
    
        if B == 2:
            return multiply_matrix(matrix, matrix)
    
        if B % 2 == 0:
            matrix = pow_matrix(pow_matrix(matrix, B//2), 2)
    
        else:
            matrix = multiply_matrix(pow_matrix(
                pow_matrix(matrix, B//2), 2), matrix)
    
        return matrix

    ์ง€์ˆ˜๊ฐ€ ๋งค์šฐ ํฌ๊ธฐ ๋•Œ๋ฌธ์— ํ–‰๋ ฌ์„ ๋ฐ˜๋ณต์ ์œผ๋กœ ๊ณฑํ•˜๋ฉด ์‹œ๊ฐ„์ดˆ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฏ€๋กœ ๋ถ„ํ•  ์ •๋ณต ๊ธฐ๋ฒ•์„ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ์ˆ˜์‹์œผ๋กœ ํšจ์œจ์ ์œผ๋กœ ๊ณ„์‚ฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. 

    •  B๊ฐ€ ์ง์ˆ˜์ผ ๊ฒฝ์šฐ:  $A^B = A^{B/2} \times A^{B/2}$

    •  B๊ฐ€ ํ™€์ˆ˜์ผ ๊ฒฝ์šฐ:  $A^B = A \times A^{B-1} = A \times A^{(B-1)/2} \times A^{(B-1)/2}$

    B๊ฐ€ ์ง์ˆ˜์ผ ๋•Œ์™€ ํ™€์ˆ˜์ธ ๊ฒฝ์šฐ ๊ฐ๊ฐ์˜ ์ˆ˜์‹์œผ๋กœ ์žฌ๊ท€์ ์œผ๋กœ ๋“ค์–ด๊ฐ€๋„๋ก ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

    ๊ทธ๋ฆฌ๊ณ  ์žฌ๊ท€ํ•จ์ˆ˜์˜ base case๊ฐ€ ๋˜๋Š” ์กฐ๊ฑด์€ B๊ฐ€ 1์ผ ๋•Œ์™ธ 2์ผ ๋•Œ์ž…๋‹ˆ๋‹ค. B๊ฐ€ 2์ผ ๋•Œ๋Š” ํ–‰๋ ฌ์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ์„ ๊ณ„์‚ฐ(multiply_matrix() ํ•จ์ˆ˜)ํ•˜์—ฌ ๋ฆฌํ„ดํ•˜๊ณ , B๊ฐ€ 1์ผ ๋•Œ๋Š” ๋ชจ๋“  ์›์†Œ๋ฅผ 1000์œผ๋กœ ๋‚˜๋ˆˆ ๋‚˜๋จธ์ง€๋กœ ๋ฐ”๊พธ์–ด ๊ทธ๋Œ€๋กœ ๋ฆฌํ„ดํ•ฉ๋‹ˆ๋‹ค!

     

    3) ๋‘ ํ–‰๋ ฌ์„ ๊ณฑํ•˜๋Š” ํ•จ์ˆ˜

    def multiply_matrix(A, B):
        """
        ๋‘ ํ–‰๋ ฌ A, B๋ฅผ ๊ณฑํ•˜๋Š” ํ•จ์ˆ˜
        """
        n = len(A)
        result = [[0] * n for _ in range(n)]
        for i in range(n):
            for j in range(n):
                result[i][j] = sum(
                    [(a * b) for a, b in zip(A[i], [b[j] for b in B])]) % 1000
        return result

     

    ํ–‰๋ ฌ์„ ๊ฑฐ๋“ญ์ œ๊ณฑํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋Š” pow_matrix() ํ•จ์ˆ˜์•ˆ์—์„œ ํ˜ธ์ถœ๋˜๋Š”๋ฐ, B=2์ธ ๊ธฐ์ € ์กฐ๊ฑด์— ๊ฑธ๋ฆด ๋•Œ์™€ B๊ฐ€ ํ™€์ˆ˜์ธ ๊ฒฝ์šฐ, $A \times A^{B-1}$๋ฅผ ๊ณ„์‚ฐํ•  ๋•Œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

     

    4) ์ถœ๋ ฅํ•˜๊ธฐ

    for row in result:
        print(' '.join(map(str, row)))

     

    ๐ŸŒฑ ์ •๋‹ต ์ฝ”๋“œ

    # !/usr/bin/python
    # -*- coding: utf-8 -*-
    # boj 10830 ํ–‰๋ ฌ์ œ๊ณฑ
    
    import sys
    
    input = sys.stdin.readline
    
    
    def multiply_matrix(A, B):
        n = len(A)
        result = [[0] * n for _ in range(n)]
        for i in range(n):
            for j in range(n):
                result[i][j] = sum(
                    [(a * b) for a, b in zip(A[i], [b[j] for b in B])]) % 1000
        return result
    
    
    def pow_matrix(matrix, B):
        if B == 1:
            return [[element % 1000 for element in row] for row in matrix]
    
        if B == 2:
            return multiply_matrix(matrix, matrix)
    
        if B % 2 == 0:
            matrix = pow_matrix(pow_matrix(matrix, B//2), 2)
        else:
            matrix = multiply_matrix(pow_matrix(
                pow_matrix(matrix, B//2), 2), matrix)
                
        return matrix
    
    
    N, B = map(int, input().split())
    matrix = []
    
    for _ in range(N):
        matrix.append(list(map(int, input().split())))
    
    result = pow_matrix(matrix, B)
    
    for row in result:
        print(' '.join(map(str, row)))
    ๋ฐ˜์‘ํ˜•

    ๋Œ“๊ธ€