#include <algorithm> #include <cassert> #include <iostream> #include <vector> #include <string> #include <memory> #include <unordered_map> #include <unordered_set> using ll = long long; using vec_bool = std::vector<bool>*; struct VectorHash { size_t operator()(const vec_bool v) const { const std::hash<std::vector<bool>> hasher; return hasher(*v); } }; struct VectorEquals { bool operator()(const vec_bool a, const vec_bool b) const { return *a == *b; } }; ll n, m, p; std::vector<bool>* prev; std::vector<vec_bool> ways_tmp; std::unordered_map<vec_bool, ll> ways, ways2; std::unordered_map<vec_bool, std::vector<vec_bool>, VectorHash, VectorEquals> cache; std::unordered_map<vec_bool, std::vector<vec_bool>, VectorHash, VectorEquals>::const_iterator try_to_paint() { auto it = cache.find(prev); if(it != cache.end()) { return it; } ways_tmp.clear(); static std::vector<bool> starting_points(m, false); std::fill(starting_points.begin(), starting_points.end(), false); for(int i = 0; i < prev->size(); ++i) { if((*prev)[i]) { std::vector<bool> tmp(m, false); for(int up = i; up >= 0; --up) { if(starting_points[up]) break; tmp[up] = true; ways_tmp.push_back(new std::vector<bool>(tmp.begin(), tmp.end())); for(int down = i + 1; down < m; ++down) { tmp[down] = true; ways_tmp.push_back(new std::vector<bool>(tmp.begin(), tmp.end())); } std::fill(tmp.begin() + i + 1, tmp.end(), false); } starting_points[i] = true; } //std::cout << i << " " << ways_tmp.size() << std::endl; } //std::cout << "CALC" << std::endl; return cache.insert({prev, ways_tmp}).first; } ll solve() { auto it = try_to_paint(); for(auto* const x : it->second) ways[x] = 1; for(int i = 1; i < n; ++i) { //std::cout << i << std::endl; for(const auto& x : ways) { prev = x.first; it = try_to_paint(); for(auto* const y : it->second) ways2[y] = (ways2[y] + x.second) % p; } ways.clear(); ways.swap(ways2); } ll result = 0; for(const auto& x : ways) { result = (result + x.second) % p; } return result; } int main() { std::ios::sync_with_stdio(false); std::cin >> n >> m >> p; prev = new std::vector<bool>(m, true); //ways_tmp.reserve(10000000); std::cout << solve(); return 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 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #include <algorithm> #include <cassert> #include <iostream> #include <vector> #include <string> #include <memory> #include <unordered_map> #include <unordered_set> using ll = long long; using vec_bool = std::vector<bool>*; struct VectorHash { size_t operator()(const vec_bool v) const { const std::hash<std::vector<bool>> hasher; return hasher(*v); } }; struct VectorEquals { bool operator()(const vec_bool a, const vec_bool b) const { return *a == *b; } }; ll n, m, p; std::vector<bool>* prev; std::vector<vec_bool> ways_tmp; std::unordered_map<vec_bool, ll> ways, ways2; std::unordered_map<vec_bool, std::vector<vec_bool>, VectorHash, VectorEquals> cache; std::unordered_map<vec_bool, std::vector<vec_bool>, VectorHash, VectorEquals>::const_iterator try_to_paint() { auto it = cache.find(prev); if(it != cache.end()) { return it; } ways_tmp.clear(); static std::vector<bool> starting_points(m, false); std::fill(starting_points.begin(), starting_points.end(), false); for(int i = 0; i < prev->size(); ++i) { if((*prev)[i]) { std::vector<bool> tmp(m, false); for(int up = i; up >= 0; --up) { if(starting_points[up]) break; tmp[up] = true; ways_tmp.push_back(new std::vector<bool>(tmp.begin(), tmp.end())); for(int down = i + 1; down < m; ++down) { tmp[down] = true; ways_tmp.push_back(new std::vector<bool>(tmp.begin(), tmp.end())); } std::fill(tmp.begin() + i + 1, tmp.end(), false); } starting_points[i] = true; } //std::cout << i << " " << ways_tmp.size() << std::endl; } //std::cout << "CALC" << std::endl; return cache.insert({prev, ways_tmp}).first; } ll solve() { auto it = try_to_paint(); for(auto* const x : it->second) ways[x] = 1; for(int i = 1; i < n; ++i) { //std::cout << i << std::endl; for(const auto& x : ways) { prev = x.first; it = try_to_paint(); for(auto* const y : it->second) ways2[y] = (ways2[y] + x.second) % p; } ways.clear(); ways.swap(ways2); } ll result = 0; for(const auto& x : ways) { result = (result + x.second) % p; } return result; } int main() { std::ios::sync_with_stdio(false); std::cin >> n >> m >> p; prev = new std::vector<bool>(m, true); //ways_tmp.reserve(10000000); std::cout << solve(); return 0; } |