Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize("Ofast,no-stack-protector")
- #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
- #pragma GCC optimize("unroll-loops")
- #pragma GCC optimize("fast-math")
- #pragma GCC optimize("section-anchors")
- #pragma GCC optimize("profile-values,profile-reorder-functions,tracer")
- #pragma GCC optimize("vpt")
- #pragma GCC optimize("rename-registers")
- #pragma GCC optimize("move-loop-invariants")
- #pragma GCC optimize("unswitch-loops")
- #pragma GCC optimize("function-sections")
- #pragma GCC optimize("data-sections")
- #pragma GCC optimize("branch-target-load-optimize")
- #pragma GCC optimize("branch-target-load-optimize2")
- #pragma GCC optimize("btr-bb-exclusive")
- #define _CRT_SECURE_NO_WARNINGS
- #include <cmath>
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <ctime>
- #include <random>
- #include <algorithm>
- #include <bitset>
- #include <complex>
- #include <deque>
- #include <iomanip>
- #include <ios>
- #include <iostream>
- #include <iterator>
- #include <locale>
- #include <map>
- #include <memory>
- #include <new>
- #include <ostream>
- #include <queue>
- #include <set>
- #include <sstream>
- #include <stack>
- #include <string>
- #include <typeinfo>
- #include <utility>
- #include <valarray>
- #include <vector>
- #include <string>
- #include <array>
- #include <unordered_map>
- #include <unordered_set>
- #include <cassert>
- using namespace std;
- using ll = long long;
- using ld = long double;
- using itn = int;
- //using dd = double;
- mt19937 gen(41);
- //const dd eps = 1e-7;
- //const ll MAXN = 2097152;
- const ll INF = 1e9;
- //const dd pi = acos(dd(-1));
- //#define endl '\n'
- ll gcd(ll a, ll b) {
- a = abs(a);
- b = abs(b);
- while (b) {
- a %= b;
- swap(a, b);
- }
- return a;
- }
- ll binpow(ll a, ll n, ll binpow_mod = 1e9 + 7) {
- ll res = 1;
- while (n) {
- if (n & 1)
- res *= a;
- a *= a;
- n >>= 1;
- a %= binpow_mod;
- res %= binpow_mod;
- }
- return res;
- }
- struct Point {
- ll x, y;
- bool z;
- void scan() {
- cin >> x >> y;
- }
- Point(ll X = 0, ll Y = 0, bool Z = 0) {
- x = X;
- y = Y;
- z = Z;
- }
- ll operator*(Point &a) {
- return x * a.y - y * a.x;
- }
- bool operator==(Point &a) {
- return x == a.x && y == a.y;
- }
- };
- /** SOLVE
- SOLVE
- **/
- const int mod = 1e9 + 7;
- struct number {
- int x = 0;
- number() {
- x = 0;
- }
- number(int X) {
- x = X;
- }
- number operator +=(const number &a) {
- x = x + a.x;
- if (x > mod)
- x -= mod;
- return *this;
- }
- number operator +(const number &a) {
- number c = *this;
- return c += a;
- }
- number operator -=(const number &a) {
- x = x - a.x;
- if (x < 0)
- x += mod;
- return *this;
- }
- number operator -(const number &a) {
- number c = *this;
- return c -= a;
- }
- bool operator ==(number &a) {
- return (x == a.x);
- }
- bool operator ==(int a) {
- return (x == a);
- }
- };
- bool ch(ll x, ll y, ll n, ll m) {
- return x >= 0 && y >= 0 && x < n && y < m;
- }
- number check(ll n, ll m) {
- number cnt = 0;
- for (ll mask = 0; mask < (1 << (n * m)); mask++) {
- bool f = true;
- for (ll i = 0; i < n; i++) {
- if (!f)
- break;
- for (ll j = 0; j < m; j++) {
- if (ch(i + 1, j, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << ((i + 1) * m + j)))) {
- f = false;
- break;
- }
- }
- if (ch(i, j + 1, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << (i * m + j + 1)))) {
- f = false;
- break;
- }
- }
- if (ch(i + 1, j + 1, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << ((i + 1) * m + j + 1)))) {
- f = false;
- break;
- }
- }
- if (ch(i - 1, j, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << ((i - 1) * m + j)))) {
- f = false;
- break;
- }
- }
- if (ch(i, j - 1, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << (i * m + j - 1)))) {
- f = false;
- break;
- }
- }
- if (ch(i - 1, j - 1, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << ((i - 1) * m + j - 1)))) {
- f = false;
- break;
- }
- }
- if (ch(i + 1, j - 1, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << ((i + 1) * m + j - 1)))) {
- f = false;
- break;
- }
- }
- if (ch(i - 1, j + 1, n, m)) {
- if ((mask & (1 << (i * m + j))) && (mask & (1 << ((i - 1) * m + j + 1)))) {
- f = false;
- break;
- }
- }
- }
- }
- if (f)
- cnt += 1;
- }
- return cnt;
- }
- const int MAXN = 100000;
- int main() {
- #ifdef _DEBUG
- freopen("input.txt", "r", stdin);
- freopen("output.txt", "w", stdout);
- #else
- //freopen("input.txt", "r", stdin);
- //freopen("output.txt", "w", stdout);
- #endif // DEBUG
- ios_base::sync_with_stdio(false);
- cin.tie(0);
- cout << fixed << setprecision(20);
- //-----------------------------------------------//
- int n, m;
- cin >> n >> m;
- if (n == 1 && m == 1) {
- cout << 2;
- return 0;
- }
- if (n == 1)
- swap(n, m);
- if (m == 1) {
- vector<int> f(n + 10);
- f[1] = 1;
- f[2] = 1;
- for (int i = 3; i < n + 7; i++) {
- f[i] = (f[i - 1] + f[i - 2]) % mod;
- }
- cout << f[n + 2];
- return 0;
- }
- unordered_map<int, int> good[2], first;
- good[0].max_load_factor(0.5);
- good[0].reserve(MAXN);
- for (int i = 0; i < 1; i++) {
- good[i].max_load_factor(0.5);
- good[i].reserve(MAXN);
- for (int mask = 0; mask < (1 << (n + 1)); mask++) {
- bool f = true;
- if (!f)
- continue;
- for (int j = n - i; j < n; j++) {
- if ((mask & (1 << j)) && (mask & (1 << (j + 1)))) {
- f = false;
- break;
- }
- }
- for (int j = 0; j < n - 1 - i; j++) {
- if ((mask & (1 << j)) && (mask & (1 << (j + 1)))) {
- f = false;
- break;
- }
- }
- if (!f)
- continue;
- if (i == 0) {
- if ((mask & 1) && (mask & (1 << n)))
- continue;
- if (n > 1 && (mask & 2) && (mask & (1 << n)))
- continue;
- int sz = good[i].size();
- good[i][mask] = sz;
- }
- else {
- if ((mask & 1) && (mask & (1 << n)))
- continue;
- if (i < n - 1 && (mask & 2) && (mask & (1 << n)))
- continue;
- if ((mask & 1) && (mask & (1 << (n - 1))))
- continue;
- int sz = good[i].size();
- good[i][mask] = sz;
- }
- }
- }
- first = good[0];
- int g[25][MAXN][2];
- for (int i = 0; i < n; i++)
- for (int j = 0; j < MAXN; j++)
- for (int k = 0; k < 2; k++)
- g[i][j][k] = -1;
- int kek = 1;
- for (int i = 0; i < n; i++) {
- kek ^= 1;
- good[1 ^ kek].clear();
- good[1 ^ kek].max_load_factor(0.5);
- good[1 ^ kek].reserve(MAXN);
- if (i != n - 1) {
- i++;
- for (int mask = 0; mask < (1 << (n + 1)); mask++) {
- bool f = true;
- for (int j = 0; j < n - 1 - i; j++) {
- if ((mask & (1 << j)) && (mask & (1 << (j + 1)))) {
- f = false;
- break;
- }
- }
- if (!f)
- continue;
- for (int j = n - i; j < n; j++) {
- if ((mask & (1 << j)) && (mask & (1 << (j + 1)))) {
- f = false;
- break;
- }
- }
- if (!f)
- continue;
- if (i == 0) {
- if ((mask & 1) && (mask & (1 << n)))
- continue;
- if (n > 1 && (mask & 2) && (mask & (1 << n)))
- continue;
- int sz = good[1 ^ kek].size();
- good[1 ^ kek][mask] = sz;
- }
- else {
- if ((mask & 1) && (mask & (1 << n)))
- continue;
- if (i < n - 1 && (mask & 2) && (mask & (1 << n)))
- continue;
- if ((mask & 1) && (mask & (1 << (n - 1))))
- continue;
- int sz = good[1 ^ kek].size();
- good[1 ^ kek][mask] = sz;
- }
- }
- i--;
- }
- else {
- swap(good[1 ^ kek], first);
- }
- if (i == n - 1) {
- for (auto k : good[0 ^ kek]) {
- int mask = k.first;
- int to = k.second;
- int m0 = (mask >> 1);
- int m1 = (mask >> 1) | (1 << n);
- bool f1, f2;
- f1 = mask & (2);
- f2 = mask & (4);
- if (good[1 ^ kek].count(m0))
- g[i][to][0] = good[1 ^ kek][m0];
- if (!f1 && !f2)
- if (good[1 ^ kek].count(m1))
- g[i][to][1] = good[1 ^ kek][m1];
- }
- }
- else {
- for (auto k : good[0 ^ kek]) {
- int mask = k.first;
- int to = k.second;
- int m0 = (mask >> 1);
- int m1 = (mask >> 1) | (1 << n);
- bool f1, f2, f3, f4;
- f1 = mask & (1 << n);
- f2 = mask & (1);
- f3 = mask & (2);
- if (i == n - 2)
- f4 = false;
- else
- f4 = mask & (4);
- if (good[1 ^ kek].count(m0))
- g[i][to][0] = good[1 ^ kek][m0];
- if (!f1 && !f2 && !f3 && !f4)
- if (good[1 ^ kek].count(m1))
- g[i][to][1] = good[1 ^ kek][m1];
- }
- }
- }
- int a[25][MAXN];
- fill(a[0], a[0] + MAXN, 1);
- for (int I = 1; I < m; I++) {
- for (int j = 0; j < n; j++) {
- if (I == m - 1 && j == n - 1)
- break;
- fill(a[(j + 1) % n], a[(j + 1) % n] + MAXN, 0);
- for (int k = 0; k < MAXN; k++) {
- if (a[j][k]) {
- for (int i = 0; i < 2; i++) {
- int to = g[j][k][i];
- if (to != -1) {
- a[(j + 1) % n][to] += a[j][k];
- if (a[(j + 1) % n][to] >= mod)
- a[(j + 1) % n][to] -= mod;
- }
- }
- }
- }
- fill(a[j], a[j] + MAXN, 0);
- }
- }
- int cnt = 0;
- for (int i = 0; i < MAXN; i++) {
- cnt += a[n - 1][i];
- if (cnt >= mod)
- cnt -= mod;
- }
- cout << cnt;
- //-----------------------------------------------//
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement