반응형

https://www.acmicpc.net/problem/12850

 

12850번: 본대 산책2

가능한 경로의 수를 1,000,000,007로 나눈 나머지를 출력한다.

www.acmicpc.net

 

 

[ 문제풀이 ]

 

준영이가 정보관에서 1분 후 이동할 수 있는 건물은 전산관과 미래관입니다. 또한 전산관에서 1분 후 이동할 수 있는 건물은 신양관, 미래관 그리고 정보관입니다. 이를 행렬로 표현하면 다음과 같습니다.

 

그렇다면 각 건물에서 2분 후 이동할 수 있는 건물은 어떻게 구할 수 있을까요? 바로 1분 후 이동할 수 있는 건물들에 대한 행렬을 서로 곱하면 됩니다.

 

따라서 n분 후 이동할 수 있는 건물을 구하는 방법은 다음과 같습니다.

 

n % 2 == 0 일 때

mat( n / 2 ) * mat( n / 2 )

 

n % 2 == 1 일 때

mat( n - 1 ) * mat( 1 )

 

재귀를 통해 D번 이동했을 때 mat( D )의 0 , 0의 값을 출력하면 정보과학관으로 돌아오는 경우의 수를 구할 수 있습니다.

 

[ 소스 코드 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <vector>
#include <unordered_map>
 
#define ll long long
 
using namespace std;
 
vector<vector<ll>> mat = {        //연결되어 있으면 1
    {0,1,1,0,0,0,0,0},
    {1,0,1,1,0,0,0,0},
    {1,1,0,1,1,0,0,0},
    {0,1,1,0,1,1,0,0},
    {0,0,1,1,0,1,1,0},
    {0,0,0,1,1,0,0,1},
    {0,0,0,0,1,0,0,1},
    {0,0,0,0,0,1,1,0}
};
 
int D;
ll MOD = 1000000007;
unordered_map<intvector<vector<ll>>> m;
 
vector<vector<ll>> multi(vector<vector<ll>> A, vector<vector<ll>> B)    //A, B 행렬 곱
{
    vector<vector<ll>> ret;
    for (int i = 0; i < 8; i++) {
        vector<ll> tmp;
        for (int j = 0; j < 8; j++) {
            ll sum = 0;
            for (int k = 0; k < 8; k++) {
                sum += A[i][k] * B[k][j];
                sum %= MOD;
            }
            tmp.push_back( sum );
        }
        ret.push_back( tmp );
    }
 
    return ret;
}
 
vector<vector<ll>> dfs(int num)        //행렬을 num번 곱했을 때 배열
{
    if (m.find(num) != m.end()) {
        return m[num];
    }
    if (num % 2 == 0) {
        return m[num] = multi(dfs(num / 2), dfs(num / 2));
    }
    else {
        return m[num] = multi(dfs(num - 1), dfs(1));
    }
}
 
int main()
{
    cin >> D;
 
    m[1= mat;
 
    dfs(D);
 
    cout<<m[D][0][0];
}
cs
반응형

+ Recent posts