본문 바로가기

백준

12850 본대 산책2

인접행렬 제곱으로 풀 수 있는 문제

총 D분만 움직이고 마지막에 정보대에 도착해야 하니 행렬 제곱의 결과 중 정보대만 확인하면 경우의 수를 알 수 있다. 

 

#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <functional>
#include <string>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <cmath>
#include <cstring>
#include <bitset>

#define xx first
#define yy second
#define all(x) (x).begin(), (x).end()

using namespace std;
using i64 = long long int;
using ii = pair<int, int>;
using ii64 = pair<i64, i64>;

using matrix = vector<vector<long long>>;
const int MOD = 1e9 + 7;

matrix operator * (matrix const& a, matrix const& b) {
	matrix ret(a.size(), vector<long long>(b[0].size()));
	for (int i = 0; i < a.size(); i++) 
	    for (int j = 0; j < b.size(); j++) 
	        for (int k = 0; k < b[0].size(); k++) {
		        ret[i][k] = (ret[i][k] + a[i][j] * b[j][k]) % MOD;
	}
	return ret;
}

matrix ipow(matrix map, int x)
{
    if (x == 0) {
        matrix one(map.size(), vector<long long>(map.size()));
        for (int i = 0; i < map.size(); i++) 
            one[i][i] = 1;
        return one;
    }

    matrix half = ipow(map, x / 2);
    half = half * half;

    if (x % 2 == 0)
        return half;

    return half * map;
}

int     main()
{
    int n;
    scanf("%d", &n);
    
    matrix map = {
        {0, 1, 0, 0, 1, 0 ,0, 0},
        {1, 0, 1, 0, 1, 0, 0, 0},
        {0, 1, 0, 1, 1, 0, 1, 0},
        {0, 0, 1, 0, 0, 1, 1, 0},
        {1, 1, 1, 0, 0, 0, 1, 0},
        {0, 0, 0, 1, 0, 0, 0, 1},
        {0, 0, 1, 1, 1, 0, 0, 1},
        {0, 0, 0, 0, 0, 1, 1, 0}
    };
    map = ipow(map, n);
	printf("%d", map[0][0]);

    return 0;
}

'백준' 카테고리의 다른 글

20149 선분 교차 3  (0) 2021.07.18
2090 조화평균  (0) 2021.07.17
16938 캠프 준비  (0) 2021.07.17
12916 K-Path  (0) 2021.07.17
11423 Primes  (0) 2021.05.15