Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #pragma GCC optimize("Ofast")
- #pragma GCC target("sse,sse2,sse3,ssse3,sse4")
- #define mp make_pair
- #define mt make_tuple
- #define all(x) (x).begin(), (x).end()
- #define rall(x) (x).rbegin(), (x).rend()
- #define sz(x) int((x).size())
- using namespace std;
- //typedef __int128 vll;
- mt19937 gen_rand;
- /*OUTPUT*/
- /*PAIR*/
- /*
- void read(vll &x) {
- string s;
- cin >> s;
- x = 0;
- int buf = 1;
- for (auto c : s) {
- if (c == '-') {
- assert(buf != -1);
- buf = -1;
- continue;
- }
- x *= 10;
- x += (c - '0');
- }
- x *= buf;
- }
- ostream &operator<<(ostream &os, vll x) {
- deque<char> res;
- int buf = 0;
- if (x < 0) {
- buf = 1;
- x = -x;
- res.push_back('-');
- }
- bool flag = false;
- while (x > 0 || !flag) {
- flag = true;
- res.push_back(char('0' + x % 10));
- x /= 10;
- }
- reverse(res.begin() + buf, res.end());
- for (auto c : res) {
- os << c;
- }
- return os;
- }
- */
- template<typename T, typename U>
- ostream &operator<<(ostream &os, pair<T, U> &a) {
- os << "(";
- os << a.first << ", ";
- os << a.second;
- os << ")";
- return os;
- }
- /*PAIR*/
- /*ARR*/
- template<typename T>
- ostream &operator<<(ostream &os, vector<T> &a) {
- os << "{";
- bool was = false;
- for (auto &x: a) {
- if (was) {
- os << ", ";
- }
- was = true;
- os << x;
- }
- os << "}";
- return os;
- }
- /*ARR*/
- /*OUTPUT*/
- /*DEBUG*/
- template<typename T>
- inline void debug(const char* sdbg, T x) {
- cerr << "The value of " << sdbg << " is " << x << "\n";
- };
- template<typename T, typename... U>
- inline void debug(const char* sdbg, T h, U... t) {
- cerr << "The value of ";
- while (*sdbg != ',') {
- cerr << *sdbg++;
- }
- cerr << " is " << h << "\n";
- debug(sdbg + 1, t...);
- cerr << "\n";
- }
- #define value(...) debug(#__VA_ARGS__, __VA_ARGS__)
- /*DEBUG*/
- template<typename T>
- T abs(T x) {
- if (x < 0) {
- return -x;
- } else {
- return x;
- }
- }
- template<typename T>
- T sqr(T x) {
- return x * x;
- };
- const long long INF_FOR_SHORT_TIME = (long long)(1e9);
- template<typename T>
- T mul(T a, T b, T m) {
- if (a <= INF_FOR_SHORT_TIME && b <= INF_FOR_SHORT_TIME) {
- return (a * b) % m;
- }
- T q = (long long)((long double)a * (long double)b / (long double)m);
- T r = a * b - q * m;
- return (r + 5 * m) % m;
- }
- template<typename T, typename U>
- T binpow(T a, U n, T MOD) {
- T res = 1;
- while (n) {
- if (n & 1) {
- res = mul(res, a, MOD);
- }
- a = mul(a, a, MOD);
- n >>= 1;
- }
- return res;
- };
- template<typename T>
- int sign(T x) {
- if (x < 0) {
- return -1;
- } else if (x > 0) {
- return 1;
- } else {
- return 0;
- }
- };
- template<typename T>
- T gcd(T a, T b) {
- if (a > b) {
- swap(a, b);
- }
- while (a) {
- b %= a;
- swap(a, b);
- }
- return b;
- };
- template<typename T>
- bool uin(T &a, T b) {
- if (a > b) {
- a = b;
- return true;
- }
- return false;
- };
- template<typename T>
- bool uax(T &a, T b) {
- if (a < b) {
- a = b;
- return true;
- }
- return false;
- };
- typedef unsigned int uint;
- typedef unsigned long long ull;
- typedef long long ll;
- typedef long double ld;
- /*curlink v1.9 + 128*/
- const int mod = int(1e9) + 7;
- const int N = 25;
- const int NUS = 271444;
- int n, m, maxn;
- int get(int mask, int ind) {
- return (mask >> ind) & 1;
- }
- void del(int &mask, int ind) {
- if ((mask >> ind) & 1) {
- mask ^= (1 << ind);
- }
- }
- int main() {
- gen_rand.seed(time(0));
- ios_base::sync_with_stdio(false);
- cin.tie(nullptr);
- cout.tie(nullptr);
- cin >> n >> m;
- if (n > m) {
- swap(n, m);
- }
- if (n == 1) {
- int dp[m + 1][2] = {};
- dp[1][0] = 1;
- dp[1][1] = 1;
- for (int len = 2; len <= m; ++len) {
- dp[len][0] = (dp[len - 1][0] + dp[len - 1][1]) % mod;
- dp[len][1] = dp[len - 1][0];
- }
- cout << (dp[m][0] + dp[m][1]) % mod;
- return 0;
- }
- maxn = (1 << (n + 1));
- int us[N][NUS], mv[N][NUS], rv[N][NUS];
- uint index[N];
- {
- vector<int> can[N + 1];
- can[1].push_back(0);
- can[1].push_back(1);
- for (int len = 2; len <= n; ++len) {
- int bt = (1 << (len - 1));
- for (auto fr : can[len - 1]) {
- int x = get(fr, len - 2);
- if (x) {
- can[len].push_back(fr);
- } else {
- can[len].push_back(fr);
- can[len].push_back(fr + bt);
- }
- }
- }
- for (int i = 0; i < n; ++i) {
- for (auto mask0 : can[i + 1]) {
- for (auto mask1 : can[n - i]) {
- if (get(mask0, 0) & get(mask1, 0)) {
- continue;
- }
- if (get(mask0, 1) & get(mask1, 0)) {
- continue;
- }
- if (get(mask0, 0) & get(mask1, 1)) {
- continue;
- }
- us[i][index[i]] = (mask0 + (mask1 << (i + 1)));
- int mask = (mask0 + (mask1 << (i + 1)));
- int nw = mask;
- for (int k = i + 2; k <= n; ++k) {
- del(nw, k - 1);
- nw += (1 << (k - 1)) * get(nw, k);
- }
- del(nw, n);
- nw <<= 1;
- mv[i][index[i]] = (nw);
- nw = 0;
- int ct = 1;
- for (int k = n - 1; k >= 0; --k) {
- int x = get(mask, k);
- if (x) {
- nw ^= (1 << ct);
- }
- ++ct;
- }
- rv[i][index[i]] = (nw);
- ++index[i];
- }
- }
- }
- }
- for (int i = 0; i < n; ++i) {
- int nxt = (i + 1) % n;
- unordered_map<int, int> pos;
- for (int k = 0; k < index[nxt]; ++k) {
- pos[us[nxt][k]] = k;
- }
- if (i + 1 < n) {
- for (int k = 0; k < index[i]; ++k) {
- int nw = mv[i][k];
- if (pos.count(nw)) {
- rv[i][k] = pos[nw];
- } else {
- rv[i][k] = -1;
- }
- }
- for (int k = 0; k < index[i]; ++k) {
- int nw = mv[i][k] + 1;
- if (pos.count(nw)) {
- mv[i][k] = pos[nw];
- } else {
- mv[i][k] = -1;
- }
- }
- } else {
- for (int k = 0; k < index[i]; ++k) {
- int nw = rv[i][k] + 1;
- if (pos.count(nw)) {
- mv[i][k] = pos[nw];
- } else {
- mv[i][k] = -1;
- }
- }
- for (int k = 0; k < index[i]; ++k) {
- int nw = rv[i][k];
- if (pos.count(nw)) {
- rv[i][k] = pos[nw];
- } else {
- rv[i][k] = -1;
- }
- }
- }
- }
- const int timer = -1;
- int cur[NUS], nw_cur[NUS];
- for (int i = 0; i < index[0]; ++i) {
- cur[i] = 1;
- }
- int lst = 0;
- for (int i = 0; i < n; ++i) {
- if (i + 1 < n) {
- for (int k = 0; k < index[i]; ++k) {
- int mask = us[i][k];
- if (get(mask, 0) || get(mask, i + 1) || get(mask, i + 2) || get(mask, i + 3)) {
- mv[i][k] = -1;
- }
- }
- } else {
- for (int k = 0; k < index[i]; ++k) {
- int mask = us[i][k];
- if (get(mask, i) || (i > 0 && get(mask, i - 1))) {
- mv[i][k] = -1;
- }
- }
- }
- }
- for (int j = 1; j < m; ++j) {
- for (int i = 0; i < n; ++i) {
- if (i == n - 1 && j == m - 1) {
- continue;
- }
- int nxt = (i + 1) % n;
- lst = index[nxt];
- for (int k = 0; k < index[nxt]; ++k) {
- nw_cur[k] = 0;
- }
- if (i + 1 < n) {
- for (int k = 0; k < index[i]; ++k) {
- int mask = us[i][k];
- if (rv[i][k] != timer) {
- nw_cur[rv[i][k]] += cur[k];
- nw_cur[rv[i][k]] %= mod;
- }
- if (mv[i][k] != timer) {
- nw_cur[mv[i][k]] += cur[k];
- nw_cur[mv[i][k]] %= mod;
- }
- }
- } else {
- for (int k = 0; k < index[i]; ++k) {
- int mask = us[i][k];
- if (rv[i][k] != timer) {
- nw_cur[rv[i][k]] += cur[k];
- nw_cur[rv[i][k]] %= mod;
- }
- if (mv[i][k] != timer) {
- nw_cur[mv[i][k]] += cur[k];
- nw_cur[mv[i][k]] %= mod;
- }
- }
- }
- swap(cur, nw_cur);
- }
- }
- int ans = 0;
- for (int i = 0; i < lst; ++i) {
- ans += cur[i];
- ans %= mod;
- }
- cout << ans;
- return 0;
- }
- /*
- vector<vector<int>> mv(maxn, vector<int>(n));
- vector<vector<int>> rv(maxn, vector<int>(n));
- for (int mask = 0; mask < maxn; ++mask) {
- for (int i = 0; i < n; ++i) {
- int nw = mask;
- for (int k = i + 2; k <= n; ++k) {
- del(nw, k - 1);
- nw += (1 << (k - 1)) * get(nw, k);
- }
- del(nw, n);
- nw <<= 1;
- mv[mask][i] = nw;
- nw = 0;
- int ct = 1;
- for (int k = n - 1; k >= 0; --k) {
- int x = get(mask, k);
- if (x) {
- nw ^= (1 << ct);
- }
- ++ct;
- }
- rv[mask][i] = nw;
- }
- }
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement