Problem:
G: Donuts Orientation
物語
ほむちゃんの最近のマイブームはお菓子作りだ。たくさんお菓子を作っては、それを友達におすそ分けしているらしい。そんなほむちゃんは今回、ドーナツづくりに挑戦するようだ。
ドーナツづくりに大切なことはいくつもある。生地や味付けはもちろん、かわいい見た目にするためのデコレーションも外せない。試行錯誤を繰り返しているうちに、ほむちゃんのデコレーションへのこだわりに熱がこもってきたようだ。こだわりぬいたドーナツを多くの人に食べてもらいたいので、ほむちゃんはドーナツをたくさんつくりたいと考えている。
・・・ところで、こだわるのは一向に構わないが、ほむちゃんこだわりのドーナツを十分な数用意することはできるのだろうか？
問題
3
以上の整数
N
について、以下のようにして
2N
頂点のグラフを作る。
それぞれの頂点について
1
から
2N
で番号付けする。
各整数
1 \leq a \leq N
について、頂点
2a-1
と
2a
の間に無向辺を張る
各整数
1 \leq b \leq 2N-2
について、頂点
b
と
b+2
の間に無向辺を張る
頂点
1
と
2N-1
および
2
と
2N
の間に無向辺を張る
このグラフの各辺に向きをつけて、有向グラフを作る。つまり、頂点
u
と
v
の間に無向辺があるならば、それを
u
から
v
へ向かう有向辺にするか、
v
から
u
へ向かう有向辺にする。
このようにしてできた有向グラフであって、サイクルを持たないものが何通りあるかを知りたい。答えは非常に大きくなるため、素数
M
で割った余りを求めよ。
入力形式
N
M
制約
3 \leq N \leq 1,000
10^8 \leq M \leq 10^9 + 7
M
は素数であることが保証される
出力形式
条件を満たす有向グラフの数を
M
で割った余りを出力せよ。
入力例1
3 1000000007
出力例1
204
N = 3
なので、
6
頂点からなるグラフを作る。条件に合致する有向グラフの一例は以下の通りである。
サイクルが存在するため、以下に示す有向グラフは条件を満たさない。
入力例2
128 998244353
出力例2
996915100
M
で割った余りを出力することに注意せよ。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

struct ArbitraryModInt {
    int x;

    ArbitraryModInt() : x(0) {}

    ArbitraryModInt(int64_t y)
        : x(y >= 0 ? y % get_mod() : (get_mod() - (-y) % get_mod()) % get_mod()) {
    }

    static int &get_mod() {
        static int mod = 0;
        return mod;
    }

    static void set_mod(int md) { get_mod() = md; }

    ArbitraryModInt &operator+=(const ArbitraryModInt &p) {
        if ((x += p.x) >= get_mod()) x -= get_mod();
        return *this;
    }

    ArbitraryModInt &operator-=(const ArbitraryModInt &p) {
        if ((x += get_mod() - p.x) >= get_mod()) x -= get_mod();
        return *this;
    }

    ArbitraryModInt &operator*=(const ArbitraryModInt &p) {
        unsigned long long a = (unsigned long long)x * p.x;
        unsigned xh = (unsigned)(a >> 32), xl = (unsigned)a, d, m;
        asm("divl %4; \n\t" : "=a"(d), "=d"(m) : "d"(xh), "a"(xl), "r"(get_mod()));
        x = m;
        return *this;
    }

    ArbitraryModInt &operator/=(const ArbitraryModInt &p) {
        *this *= p.inverse();
        return *this;
    }

    ArbitraryModInt operator-() const { return ArbitraryModInt(-x); }

    ArbitraryModInt operator+(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) += p;
    }

    ArbitraryModInt operator-(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) -= p;
    }

    ArbitraryModInt operator*(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) *= p;
    }

    ArbitraryModInt operator/(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) /= p;
    }

    bool operator==(const ArbitraryModInt &p) const { return x == p.x; }

    bool operator!=(const ArbitraryModInt &p) const { return x != p.x; }

    ArbitraryModInt inverse() const {
        int a = x, b = get_mod(), u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return ArbitraryModInt(u);
    }

    ArbitraryModInt pow(int64_t n) const {
        ArbitraryModInt ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend ostream &operator<<(ostream &os, const ArbitraryModInt &p) {
        return os << p.x;
    }

    friend istream &operator>>(istream &is, ArbitraryModInt &a) {
        int64_t t;
        is >> t;
        a = ArbitraryModInt(t);
        return (is);
    }
};

using modint = ArbitraryModInt;

int main() {

    int n, m;
    cin >> n >> m;

    modint::set_mod(m);

    vector ts(1 << 12, map<int, int>());

    /*
        a b
        c d
        012 ab ad ac
        345 ba bc bd
        678 cd cb ca
        91011 dc da db
    */
    int mat[4][4] = {
        {-1, 0, 2, 1},
        {3, -1, 4, 5},
        {8, 7, -1, 6},
        {10, 11, 9, -1}
    };

    for (int i = 0; i < 1 << 12; ++i) {
        // 000 -> clockwise
        for (int j = 0; j < 1 << 3; ++j) {
            int nxt = 0;
            if ((i >> 5 & 1) && (~j >> 1 & 1)) continue;
            if ((i >> 11 & 1) && (j >> 1 & 1)) continue;
            nxt |= (1 << 0) * ((i >> 0 & 1) && (~j >> 2 & 1) || (i >> 1 & 1) && (~j >> 1 & 1) && (~j >> 2 & 1));
            nxt |= (1 << 1) * ((i >> 1 & 1) && (j >> 0 & 1) || (i >> 0 & 1) && (j >> 1 & 1) && (j >> 0 & 1));
            nxt |= (1 << 2) * ((i >> 2 & 1) || (i >> 0 & 1) && (i >> 9 & 1) && (j >> 1 & 1));

            nxt |= (1 << 3) * ((i >> 3 & 1) && (j >> 2 & 1) || (i >> 10 & 1) && (j >> 2 & 1) && (j >> 1 & 1));
            nxt |= (1 << 4) * ((i >> 4 & 1) && (j >> 2 & 1) || (i >> 9 & 1) && (j >> 2 & 1) && (j >> 1 & 1));
            nxt |= (1 << 5) * ((i >> 5 & 1) && (j >> 2 & 1) && (j >> 0 & 1) || (j >> 2 & 1) && (j >> 1 & 1) && (j >> 0 & 1));

            nxt |= (1 << 6) * ((i >> 6 & 1) && (j >> 0 & 1) || (i >> 7 & 1) && (j >> 1 & 1) && (j >> 0 & 1));
            nxt |= (1 << 7) * ((i >> 7 & 1) && (~j >> 2 & 1) || (i >> 6 & 1) && (~j >> 1 & 1) && (~j >> 2 & 1));
            nxt |= (1 << 8) * ((i >> 8 & 1) || (i >> 6 & 1) && (i >> 3 & 1) && (~j >> 1 & 1));

            nxt |= (1 << 9) * ((i >> 9 & 1) && (~j >> 0 & 1) || (i >> 4 & 1) && (~j >> 0 & 1) && (~j >> 1 & 1));
            nxt |= (1 << 10) * ((i >> 10 & 1) && (~j >> 0 & 1) || (i >> 3 & 1) && (~j >> 0 & 1) && (~j >> 1 & 1));
            nxt |= (1 << 11) * ((i >> 11 & 1) && (~j >> 0 & 1) && (~j >> 2 & 1) || (~j >> 2 & 1) && (~j >> 1 & 1) && (~j >> 0 & 1));
            ts[i][nxt]++;
        }
    }

    vector dp(n + 1, vector(1 << 12, modint(0)));
    dp[0][0b001001001001] = 1;

    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < 1 << 12; ++j) {
            for (auto [to, c] : ts[j]) {
                if (i == n) {
                    if (to >> 0 & 1) continue;
                    if (to >> 3 & 1) continue;
                    if (to >> 6 & 1) continue;
                    if (to >> 9 & 1) continue;
                    if ((to >> mat[1][3] & 1) && (to >> mat[2][0] & 1)) continue;
                    if ((to >> mat[3][1] & 1) && (to >> mat[0][2] & 1)) continue;
                }
                dp[i][to] += dp[i - 1][j] * c;
            }
        }
    }

    cout << accumulate(dp[n].begin(), dp[n].end(), modint(0)) << '\n';

    return (0);
}
accuracy: 1
time_ms: 170
memory_kb: 19980
final_rank: 12

code_snippet: #include <bits/stdc++.h>

using namespace std;

struct ArbitraryModInt {
    int x;

    ArbitraryModInt() : x(0) {}

    ArbitraryModInt(int64_t y)
        : x(y >= 0 ? y % get_mod() : (get_mod() - (-y) % get_mod()) % get_mod()) {
    }

    static int &get_mod() {
        static int mod = 0;
        return mod;
    }

    static void set_mod(int md) { get_mod() = md; }

    ArbitraryModInt &operator+=(const ArbitraryModInt &p) {
        if ((x += p.x) >= get_mod()) x -= get_mod();
        return *this;
    }

    ArbitraryModInt &operator-=(const ArbitraryModInt &p) {
        if ((x += get_mod() - p.x) >= get_mod()) x -= get_mod();
        return *this;
    }

    ArbitraryModInt &operator*=(const ArbitraryModInt &p) {
        unsigned long long a = (unsigned long long)x * p.x;
        unsigned xh = (unsigned)(a >> 32), xl = (unsigned)a, d, m;
        asm("divl %4; \n\t" : "=a"(d), "=d"(m) : "d"(xh), "a"(xl), "r"(get_mod()));
        x = m;
        return *this;
    }

    ArbitraryModInt &operator/=(const ArbitraryModInt &p) {
        *this *= p.inverse();
        return *this;
    }

    ArbitraryModInt operator-() const { return ArbitraryModInt(-x); }

    ArbitraryModInt operator+(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) += p;
    }

    ArbitraryModInt operator-(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) -= p;
    }

    ArbitraryModInt operator*(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) *= p;
    }

    ArbitraryModInt operator/(const ArbitraryModInt &p) const {
        return ArbitraryModInt(*this) /= p;
    }

    bool operator==(const ArbitraryModInt &p) const { return x == p.x; }

    bool operator!=(const ArbitraryModInt &p) const { return x != p.x; }

    ArbitraryModInt inverse() const {
        int a = x, b = get_mod(), u = 1, v = 0, t;
        while (b > 0) {
            t = a / b;
            swap(a -= t * b, b);
            swap(u -= t * v, v);
        }
        return ArbitraryModInt(u);
    }

    ArbitraryModInt pow(int64_t n) const {
        ArbitraryModInt ret(1), mul(x);
        while (n > 0) {
            if (n & 1) ret *= mul;
            mul *= mul;
            n >>= 1;
        }
        return ret;
    }

    friend ostream &operator<<(ostream &os, const ArbitraryModInt &p) {
        return os << p.x;
    }

    friend istream &operator>>(istream &is, ArbitraryModInt &a) {
        int64_t t;
        is >> t;
        a = ArbitraryModInt(t);
        return (is);
    }
};

using modint = ArbitraryModInt;

int main() {

    int n, m;
    cin >> n >> m;

    modint::set_mod(m);

    vector ts(1 << 12, map<int, int>());

    /*
        a b
        c d
        012 ab ad ac
        345 ba bc bd
        678 cd cb ca
        91011 dc da db
    */
    int mat[4][4] = {
        {-1, 0, 2, 1},
        {3, -1, 4, 5},
        {8, 7, -1, 6},
        {10, 11, 9, -1}
    };

    for (int i = 0; i < 1 << 12; ++i) {
        // 000 -> clockwise
        for (int j = 0; j < 1 << 3; ++j) {
            int nxt = 0;
            // if ((i >> 0 & 1) && (i >> 9 & 1) && (j >> 1 & 1)) continue;
            // if ((i >> 6 & 1) && (i >> 3 & 1) && (~j >> 1 & 1)) continue;
            if ((i >> 5 & 1) && (~j >> 1 & 1)) continue;
            if ((i >> 11 & 1) && (j >> 1 & 1)) continue;
            // for (int k = 0; k < 4; ++k) {
            //     for (int l = 0; l < 4; ++l) {
            //         for (int m = 0; m < 4; ++m) {
            //             if (mat[k][m] == -1 || mat[k][l] == -1 || mat[l][m] == -1) continue;
            //             nxt |= (1 << mat[k][m]) * ((i >> mat[k][l] & 1) && (i >> mat[l][m] & 1));
            //         }
            //     }
            // }
            nxt |= (1 << 0) * ((i >> 0 & 1) && (~j >> 2 & 1) || (i >> 1 & 1) && (~j >> 1 & 1) && (~j >> 2 & 1));
            nxt |= (1 << 1) * ((i >> 1 & 1) && (j >> 0 & 1) || (i >> 0 & 1) && (j >> 1 & 1) && (j >> 0 & 1));
            nxt |= (1 << 2) * ((i >> 2 & 1) || (i >> 0 & 1) && (i >> 9 & 1) && (j >> 1 & 1));

            nxt |= (1 << 3) * ((i >> 3 & 1) && (j >> 2 & 1) || (i >> 10 & 1) && (j >> 2 & 1) && (j >> 1 & 1));
            nxt |= (1 << 4) * ((i >> 4 & 1) && (j >> 2 & 1) || (i >> 9 & 1) && (j >> 2 & 1) && (j >> 1 & 1));
            nxt |= (1 << 5) * ((i >> 5 & 1) && (j >> 2 & 1) && (j >> 0 & 1) || (j >> 2 & 1) && (j >> 1 & 1) && (j >> 0 & 1));

            nxt |= (1 << 6) * ((i >> 6 & 1) && (j >> 0 & 1) || (i >> 7 & 1) && (j >> 1 & 1) && (j >> 0 & 1));
            nxt |= (1 << 7) * ((i >> 7 & 1) && (~j >> 2 & 1) || (i >> 6 & 1) && (~j >> 1 & 1) && (~j >> 2 & 1));
            nxt |= (1 << 8) * ((i >> 8 & 1) || (i >> 6 & 1) && (i >> 3 & 1) && (~j >> 1 & 1));

            nxt |= (1 << 9) * ((i >> 9 & 1) && (~j >> 0 & 1) || (i >> 4 & 1) && (~j >> 0 & 1) && (~j >> 1 & 1));
            nxt |= (1 << 10) * ((i >> 10 & 1) && (~j >> 0 & 1) || (i >> 3 & 1) && (~j >> 0 & 1) && (~j >> 1 & 1));
            nxt |= (1 << 11) * ((i >> 11 & 1) && (~j >> 0 & 1) && (~j >> 2 & 1) || (~j >> 2 & 1) && (~j >> 1 & 1) && (~j >> 0 & 1));
            // cout << i << ' ' << nxt << endl;
            ts[i][nxt]++;
        }
    }

    vector dp(n + 1, vector(1 << 12, modint(0)));
    dp[0][0b001001001001] = 1;

    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < 1 << 12; ++j) {
            for (auto [to, c] : ts[j]) {
                if (i == n) {
                    if (to >> 0 & 1) continue;
                    if (to >> 3 & 1) continue;
                    if (to >> 6 & 1) continue;
                    if (to >> 9 & 1) continue;
                    if ((to >> mat[1][3] & 1) && (to >> mat[2][0] & 1)) continue;
                    if ((to >> mat[3][1] & 1) && (to >> mat[0][2] & 1)) continue;
                    // if ((to >> mat[0][3] & 1) && (to >> mat[2][0] & 1)) continue;
                    // if ((to >> mat[2][1] & 1) && (to >> mat[0][2] & 1)) continue;
                    // for (int k = 0; k < 4; ++k) {
                    //     for (int l = 0; l < 4; ++l) {
                    //         if (mat[k][l] == -1 || mat[l][k] == -1) continue;
                    //         if ((to >> mat[k][l] & 1) && (to >> mat[l <= 1 ? 1 - l : 1 - (l - 2) + 2][k <= 1 ? 1 - k : 1 - (k - 2) + 2] & 1)) goto ng;
                    //     }
                    // }
                }
                dp[i][to] += dp[i - 1][j] * c;
                ng:;
            }
        }
        // cout << reduce(dp[i].begin(), dp[i].end(), modint(0)) << '\n';
    }

    cout << accumulate(dp[n].begin(), dp[n].end(), modint(0)) << '\n';

    return (0);
}
accuracy: 1
time_ms: 170
memory_kb: 19844
final_rank: 11

code_snippet: #include "bits/stdc++.h"
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
#include<map>
#include<set>
#include<iomanip>
#include<assert.h>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<stack>
#include<complex>
#pragma warning(disable:4996)
using namespace std;
using ld = long double;
template<class T>
using Table = vector<vector<T>>;
const ld eps=1e-9;
	
#define WHATS(var)//cout<<__LINE__<<' '<<#var<<"="<<var<<endl;
	
template<class S, class T> ostream& operator <<(ostream &os, const pair<S, T> v){
	os << "( " << v.first << ", " << v.second << ")"; return os;
}
template<class T> ostream& operator <<(ostream &os, const vector<T> &v){
	for(int i = 0; i < v.size(); i++){if(i > 0){os << " ";} os << v[i];} return os;
}
template<class T> ostream& operator <<(ostream &os, const vector<vector<T>> &v){
	for(int i = 0; i < v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}
template<class T> ostream& operator <<(ostream &os, const vector<set<T>> &v){
	for(int i = 0; i < v.size(); i++){if(i > 0){os << endl;} os << v[i];} return os;
}
template<class T> ostream& operator <<(ostream &os, const set<T> &v){
	int i=0;
	for(auto it:v){
		if(i > 0){os << ' ';}
		os << it;
		i++;
	} 
	return os;
}

using ll =long long ;
ll mod;

void solve(vector<vector<int>>&cango){
	int tt=cango.size();
	for(int i=0;i<tt;++i){
		for(int j=0;j<tt;++j){
			for(int k=0;k<tt;++k){
				cango[j][k]|=cango[j][i]&cango[i][k];
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(false);
	int N;cin>>N;
	cin>>mod;
	vector<vector<ll>>dp(2,vector<ll>(1<<12,false));
	{
		vector<int>v(3);
		for(;v[0]<2;++v[0]){
			for(;v[1]<2;++v[1]){
				for(;v[2]<2;++v[2]){
					vector<vector<int>>cango(4,vector<int>(4));
					if(v[0])cango[0][2]=true;
					else cango[2][0]=true;
					if(v[1])cango[1][3]=true;
					else cango[3][1]=true;
					if(v[2])cango[2][3]=true;
					else cango[3][2]=true;
					solve(cango);
					int nextj=0;
					int id=0;
					for(int x=0;x<4;++x){
						for(int y=0;y<4;++y){
							if(x==y)continue;
							else{
								if(cango[x][y])nextj|=(1<<id);
								id++;
							}
						}
					}
					dp[1][nextj]+=1;
					WHATS(cango)
				}
				v[2]=0;
			}
			v[1]=0;
		}
	}		

	for(int i=1;i<N;++i){
		int cur=i&1;
		int tar=1-cur;
		//cout<<5<<endl;
		for(int j=0;j<(1<<12);++j){
			
			if(!dp[cur][j])continue;
			vector<int>v(3);
			for(;v[0]<2;++v[0]){
				for(;v[1]<2;++v[1]){
					for(;v[2]<2;++v[2]){
						bool ok=true;
						vector<vector<int>>cango(6,vector<int>(6));
						for(int k=0;k<12;++k){
							int from=k/3;
							int to=k%3;
							if(to>=from)to++;
							if(j&(1<<k))cango[from][to]=true;
						}
						if(v[0])cango[2][4]=true;
						else cango[4][2]=true;
						if(v[1])cango[3][5]=true;
						else cango[5][3]=true;
						if(v[2])cango[4][5]=true;
						else cango[5][4]=true;
						
						WHATS(cango)
						solve(cango);
						for(int x=0;x<6;++x){
							if(cango[x][x])ok=false;

						}
						if(i==N-1&&(cango[0][4]||cango[4][0]||cango[5][1]||cango[1][5]||(cango[0][1]&&cango[5][4])||(cango[1][0]&&cango[4][5])))ok=false;
						
						if(ok){
							vector<int>all{0,1,4,5};
							int id=0;
							int nextj=0;
							for(int x=0;x<4;++x){
								for(int y=0;y<4;++y){
									if(x==y)continue;
									else{
										if(cango[all[x]][all[y]])nextj|=(1<<id);
										id++;
									}
								}
							}
							dp[tar][nextj]+=dp[cur][j];
							if(dp[tar][nextj]>=mod)dp[tar][nextj]-=mod;
						}
					}
					v[2]=0;
				}
				v[1]=0;
			}
			v[0]=0;
		}
		dp[cur]=vector<ll>(1<<12,false);
		//cout<<4<<endl;
	}
	ll answer=0;
	//cout<<6<<endl;
	for(int j=0;j<(1<<12);++j){
		
		answer+=dp[N%2][j];
	}
	answer%=mod;
	cout<<answer<<endl;
	return 0;	
}
accuracy: 1
time_ms: 210
memory_kb: 3308
final_rank: 6

code_snippet: #include<iomanip>
#include<limits>
#include<thread>
#include<utility>
#include<iostream>
#include<string>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<numeric>
#include<cassert>
#include<random>
#include<chrono>
#include<unordered_set>
#include<unordered_map>
#include<fstream>
#include<list>
#include<functional>
#include<bitset>
#include<complex>
#include<tuple>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pi;
typedef pair<double,double> pd;
typedef pair<double,ll> pdl;
#define F first
#define S second
const ll E=1e18+7;
const ll MOD=1000000007;

/*
 0 1
 2 3
 4 5
 
  0 1 2 3
0   0 1 2
1 3   4 5
2 6 7   8
3 9 10 11
*/

vector<vector<ll>> edge(6,vector<ll>(6,E));

bool Cycle(){
    for(int i=0;i<6;i++){
        for(int t=0;t<6;t++){
            for(int j=0;j<6;j++){
                edge[t][j]=min(edge[t][j],edge[t][i]+edge[i][j]);
            }
        }
    }
    for(int i=0;i<6;i++){
        if(edge[i][i]!=E){return true;}
    }
    return false;
}



int main(){
    vector<vector<ll>> A(1LL<<12,vector<ll>(1LL<<3,-1));
    vector<vector<ll>> B(1LL<<12,vector<ll>(1LL<<2,0));
    for(int i=0;i<(1LL<<12);i++){
        for(int t=0;t<(1LL<<3);t++){
            for(auto &I:edge){
                for(auto &T:I){T=E;}
            }
            for(int k=0;k<4;k++){
                for(int h=0;h<4;h++){
                    if(k==h){continue;}
                    ll w=h;
                    if(h>k){w--;}
                    if(i>>(k*3+w)&1){edge[k][h]=1;}
                }
            }
            if(t&1){edge[3][5]=1;}
            else{edge[5][3]=1;}
            if(t>>1&1){edge[2][4]=1;}
            else{edge[4][2]=1;}
            if(t>>2&1){edge[4][5]=1;}
            else{edge[5][4]=1;}
            if(Cycle()){continue;}
            ll w=0;
            for(int k=0;k<4;k++){
                for(int h=0;h<4;h++){
                    ll K=k;
                    if(K>=2){K+=2;}
                    ll H=h;
                    if(H>=2){H+=2;}
                    if(edge[K][H]!=E){
                        ll W=h;
                        if(h>k){W--;}
                        w|=(1LL<<(3*k+W));
                    }
                }
            }
            A[i][t]=w;
        }
    }
    for(int i=0;i<(1LL<<12);i++){
        for(int t=0;t<(1LL<<2);t++){
            for(auto &I:edge){
                for(auto &T:I){T=E;}
            }
            for(int k=0;k<4;k++){
                for(int h=0;h<4;h++){
                    if(k==h){continue;}
                    ll w=h;
                    if(h>k){w--;}
                    if(i>>(k*3+w)&1){edge[k][h]=1;}
                }
            }
            if(t>>0&1){edge[0][2]=1;}
            else{edge[2][0]=1;}
            if(t>>1&1){edge[1][3]=1;}
            else{edge[3][1]=1;}
            if(!Cycle()){B[i][t]=1;}
        }
    }
    
    
    ll n,m;
    cin>>n>>m;
    vector<vector<ll>> dp(n,vector<ll>(1LL<<12,0));
    for(int i=0;i<(1LL<<12);i++){
        for(auto &I:edge){
            for(auto &T:I){T=E;}
        }
        for(int k=0;k<4;k++){
            for(int h=0;h<4;h++){
                if(k==h){continue;}
                ll w=h;
                if(h>k){w--;}
                if(i>>(k*3+w)&1){edge[k][h]=1;}
            }
        }
        
        
        if(edge[0][1]+edge[1][0]!=E+1 || edge[0][2]+edge[2][0]!=E+1 || edge[1][3]+edge[3][1]!=E+1 || edge[2][3]+edge[3][2]!=E+1 || edge[0][3]!=E || edge[3][0]!=E || edge[1][2]!=E || edge[2][1]!=E){continue;}
        
        if(!Cycle()){
            ll w=0;
            for(int k=0;k<4;k++){
                for(int h=0;h<4;h++){
                    if(edge[k][h]!=E){
                        ll W=h;
                        if(h>k){W--;}
                        w|=(1LL<<(3*k+W));
                    }
                }
            }
            dp[1][w]++;
        }
    }
    
    for(int i=1;i+1<n;i++){
        for(int t=0;t<(1LL<<12);t++){
            for(int h=0;h<(1LL<<3);h++){
                if(A[t][h]!=-1){
                    dp[i+1][A[t][h]]+=dp[i][t];
                    dp[i+1][A[t][h]]%=m;
                }
            }
        }
    }
    ll ans=0;
    for(int i=0;i<(1LL<<12);i++){
        for(int k=0;k<4;k++){
            ans+=dp.back()[i]*B[i][k];
        }
    }
    ans%=m;
    cout<<ans<<endl;
    
    
    
    return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 35492
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
using Int = long long;
template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b) a=b;}
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b) a=b;}

Int MOD;
template<typename T>
struct Mint{
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }
  
  Mint inv(){return pow(MOD-2);}
  
  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}
  
  Mint operator+(Mint a) const{return Mint(v)+=a;};
  Mint operator-(Mint a) const{return Mint(v)-=a;};
  Mint operator*(Mint a) const{return Mint(v)*=a;};
  Mint operator/(Mint a) const{return Mint(v)/=a;};

  Mint operator-(){return v?MOD-v:v;}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}
};

//INSERT ABOVE HERE
const Int MAX = 1020;
using M = Mint<Int>;
M dp[2][2][2][2][2][2][2][2][2][2][MAX];

signed main(){
  Int n;
  cin>>n>>MOD;
  
  dp[0][0][1][1][0][1][1][0][1][1][0]=M(1);
  dp[1][1][1][1][1][0][0][1][1][1][0]=M(1);

  for(int i=0;i<n;i++){
    for(int top=0;top<2;top++){
      for(int prv=0;prv<2;prv++){
        for(int lul=0;lul<2;lul++){
          for(int ldl=0;ldl<2;ldl++){
            for(int lur=0;lur<2;lur++){
              for(int ldr=0;ldr<2;ldr++){                
                for(int rul=0;rul<2;rul++){
                  for(int rdl=0;rdl<2;rdl++){
                    for(int rur=0;rur<2;rur++){
                      for(int rdr=0;rdr<2;rdr++){
                        for(int nl=0;nl<2;nl++){
                          for(int nr=0;nr<2;nr++){
                            for(int na=0;na<2;na++){
                              if(prv==0&&nl==1&&nr==0&&na==1) continue;
                              if(prv==1&&nl==0&&nr==1&&na==0) continue;
                              M tmp=dp[top][prv][lul][ldl][lur][ldr][rul][rdl][rur][rdr][i];
                              int nlul=(lul&&(nl==1)) || (lur&&(nr==1)&&(na==0));
                              int nldl=(ldl&&(nl==0)) || (ldr&&(nr==0)&&(na==1));
                              int nrur=(rur&&(nr==1)) || (rul&&(nl==1)&&(na==1));
                              int nrdr=(rdr&&(nr==0)) || (rdl&&(nl==0)&&(na==0));
                              
                              int nlur=(lur&&(nr==1)) || (lul&&(nl==1)&&(na==1));
                              int nldr=(ldr&&(nr==0)) || (ldl&&(nl==0)&&(na==0));
                              int nrul=(rul&&(nl==1)) || (rur&&(nr==1)&&(na==0));
                              int nrdl=(rdl&&(nl==0)) || (rdr&&(nr==0)&&(na==1));
                              
                              dp[top][na][nlul][nldl][nlur][nldr][nrul][nrdl][nrur][nrdr][i+1]+=tmp;
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }    
    }
  }
  M ans(0);
  {
    for(int top=0;top<2;top++){
      for(int prv=0;prv<2;prv++){
        for(int lul=0;lul<2;lul++){
          for(int ldl=0;ldl<2;ldl++){
            for(int lur=0;lur<2;lur++){
              for(int ldr=0;ldr<2;ldr++){                
                for(int rul=0;rul<2;rul++){
                  for(int rdl=0;rdl<2;rdl++){
                    for(int rur=0;rur<2;rur++){
                      for(int rdr=0;rdr<2;rdr++){
                        for(int nl=0;nl<2;nl++){
                          for(int nr=0;nr<2;nr++){
                            {
                              if(top==0&&nl==0&&nr==1&&prv==1) continue;
                              if(top==1&&nl==1&&nr==0&&prv==0) continue;
                              M tmp=dp[top][prv][lul][ldl][lur][ldr][rul][rdl][rur][rdr][n-1];
                              
                              int nlul=(lul&&(nl==1));
                              int nldl=(ldl&&(nl==0));
                              int nrur=(rur&&(nr==1));
                              int nrdr=(rdr&&(nr==0));                 
                              
                              if(nlul||nldl||nrur||nrdr) continue;
                              ans+=tmp;
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }    
    }
  }
  cout<<ans.v<<endl;
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 11300
final_rank: 4

code_snippet: #include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<complex>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const ll mod = 1000000007;
typedef long double ld;
const ld INF = (ld)10000000000000;
typedef pair<int, int> P;
#define stop char nyaa;cin>>nyaa;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
typedef complex<ld> Point;
const ld eps = 1e-8;
const ld pi = acos(-1.0);
typedef pair<ld, ld> LDP;
typedef pair<ll, ll> LP;

ll dp[1001][2][4][4][4][4];
ll mod_pow(ll x, ll n, ll m) {
	ll ret = 1;
	while (n) {
		if (n % 2)ret = ret * x%m;
		x = x * x%m; n >>= 1;
	}
	return ret;
}
int main() {
	int n; ll m; cin >> n >> m;
	/*dp[0][0] = 1;
	rep1(i, n) {
		dp[i][0] = dp[i - 1][0] * 4 + dp[i - 1][1] * 3;
		dp[i][1] = dp[i - 1][1] * 4 + dp[i - 1][0] * 3;
		rep(j, 2) {
			dp[i][j] %= m;
		}
	}
	ll ans = dp[n][0] * 2 % m;
	rep1(i, n) {
		dp[i][0] = dp[i - 1][0] * 2 + dp[i - 1][1];
		dp[i][1] = dp[i - 1][1] * 2 + dp[i - 1][0] * 2;
		rep(j, 2) {
			dp[i][j] %= m;
		}
	}
	ans = ans - 8 * dp[n][0]; ans = (ans%m + m) % m;
	ll csum = 2 + mod_pow(2, n, m); csum *= 2;
	ans = (ans + csum) % m;
	cout << ans << endl;*/
	dp[0][0][3][2][1][3] = 1;
	/*dp[0][0][3][2][2][0] = 1;
	dp[0][0][3][2][0][1] = 1;
	dp[0][0][3][2][2][1] = 1;*/
	//dp[0][1][1][3][3][2] = 1;
	rep(i, n) {
		rep(j, 2) {
			rep(k, 4) {
				rep(l, 4) {
					rep(k1, 4) {
						rep(l1,4){
							rep(ul, 8) {
								int u = ul;
								if (j == 0 && u == 0)continue;
								if (j == 1 && u == 7)continue;
								int t[3];
								t[0] = u % 2; u /= 2;
								t[1] = u % 2; u /= 2;
								t[2] = u % 2;
								int x1 = 0, x2 = 0, y1 = 0, y2 = 0;
								if (k % 2 && t[0])x1 = 1;
								if (k / 2 && t[2] == 0 && t[1] == 0)x1 = 1;
								if (l % 2 && t[0])y1 = 1;
								if (l / 2 && t[2] == 0 && t[1] == 0)y1 = 1;
								if (k % 2 && t[0] && t[1])x2 = 1;
								if (k / 2 && t[2] == 0)x2 = 1;
								if (l % 2 && t[0] && t[1])y2 = 1;
								if (l / 2 && t[2] == 0)y2 = 1;

								int x3 = 0, x4 = 0, y3 = 0, y4 = 0;
								if (k1 % 2 && t[0] == 0)x3 = 1;
								if (k1 / 2 && t[2] && t[1])x3 = 1;
								if (l1 % 2 && t[0] == 0)y3 = 1;
								if (l1 / 2 && t[2] && t[1])y3 = 1;
								if (k1 % 2 && t[0] == 0 && t[1] == 0)x4 = 1;
								if (k1 / 2 && t[2])x4 = 1;
								if (l1 % 2 && t[0] == 0 && t[1] == 0)y4 = 1;
								if (l1 / 2 && t[2])y4 = 1;


								(dp[i + 1][t[1]^1][x1 + 2 * x2][y1 + 2 * y2][x3+2*x4][y3+2*y4] += dp[i][j][k][l][k1][l1]) %= m;
							}

						}
					}
				}
			}
		}
	}
	ll ans = 0;
	rep(j, 4) {
		rep(k, 4) {
			rep(j1, 4) {
				rep(k1, 4) {
					if (j % 2)continue;
					if (k / 2)continue;
					if (j1%2)continue;
					if (k1/2)continue;
					ans += dp[n][0][j][k][j1][k1]; ans %= m;
					//ans += dp[n][1][j][k][j1][k1]; ans %= m;

				}
			}
		}
	}
	//cout << ans << endl;
	cout << 2*ans%m << endl;
	//stop
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 7096
final_rank: 2

code_snippet: #include<bits/stdc++.h>
#define X first
#define Y second
#define pb emplace_back
#define FOR(i,a,b) for(int (i)=(a);i<(b);++(i))
#define EFOR(i,a,b) for(int (i)=(a);i<=(b);++(i))
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define reps(X,S,Y) for (int (X) = S;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define rreps(X,S,Y) for (int (X) = (Y)-1;(X) >= (S);--(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef ll LL;
typedef pii PII;
typedef pll PLL;
template<class T> using vv=vector<vector<T>>;
template<class T> inline bool MX(T &l,const T &r){return l<r?l=r,1:0;}
template<class T> inline bool MN(T &l,const T &r){return l>r?l=r,1:0;}

int N;
LL M;
int ord[4][4];
LL dp[1145][1 << 13];

// u -> v
bool CanReach(int st, int u, int v) {
   int idx = ord[u][v];
   return st >> idx & 1;
}

void Set(int &nst, int u, int v, bool b) {
  int idx = ord[u][v];
  if (b) nst |= 1 << idx;
  else nst &= ~(1 << idx);
}

using VC = vector<char>;
using Mat = vector<VC>;

Mat Warshal(Mat &src) {
  int m = src.size();
  Mat ret(src);

  rep(w, m) {
    rep(u, m) {
      rep(v, m) {
        ret[u][v] |= ret[u][w] & ret[w][v];
      }
    }
  }
  return move(ret);
}

int Statize(Mat &src) {
  int ret = 0;
  rep(u, 4) {
    rep(v, 4) {
      if (u == v) continue;
      if (!src[u][v]) continue;
      int idx = ord[u][v];
      ret |= 1 << idx;
    }
  }
  return ret;
}

bool HasLoop(Mat &src) {
  int m = src.size();
  rep(v, m) {
    if (src[v][v]) return true;
  }
  return false;
}

int memo2[1 << 12][8];
int memo[1 << 12][8];
pii NxtSt(int st, int d) {
  if (memo[st][d] >= 0) return pii(memo[st][d], memo2[st][d]);

  Mat con(6, VC(6, 0));
  rep(u, 4) {
    rep(v, 4) {
      if (u == v) continue;
      con[u][v] = CanReach(st, u, v);
    }
  }

  rep(k, 2) {
    bool dir = d >> k & 1;
    con[2+k][4+k] = dir;
    con[4+k][2+k] = !dir;
  }

  bool dir = d >> 2 & 1;
  con[4][5] = dir;
  con[5][4] = !dir;
  con = Warshal(con);

  int nst = 0;
  int vs[] = {0, 1, 4, 5};
  rep(i, 4) {
    int u = vs[i];
    rep(j, 4) {
      if (i == j) continue;

      int v = vs[j];
      Set(nst, i, j, con[u][v]);
    }
  }

  int loop = HasLoop(con);
  memo2[st][d] = !loop;
  memo[st][d] = nst;
  return pii(nst, !loop);
}

int main() {
  {
    int cnt = 0;
    rep(u, 4) {
      rep(v, 4) {
        if (u == v) continue;
        ord[u][v] = cnt++;
      }
    }
  }
  fill(memo[0], memo[1 << 12], -1);
  fill(memo2[0], memo2[1 << 12], -1);

  scanf("%d%lld", &N, &M);
  
  int vs[] = {0, 1, 3, 2};
  rep(d, 16) {
    Mat mat(4, VC(4, 0));
    rep(k, 4) {
      bool dir = d >> k & 1; 
      int u, v;
      u = vs[k];
      v = vs[(k+1)%4];
      mat[u][v] = dir;
      mat[v][u] = !dir;
    }
    mat = Warshal(mat);
    if (!HasLoop(mat)) dp[1][Statize(mat)] = 1;
  }

  int lim = 1 << 12;
  reps(i, 2, N) {
    rep(st, lim) {
      LL v = dp[i-1][st];
      rep(d, 8) { // dirs
        int nst;
        int ok;
        tie(nst, ok) = NxtSt(st, d);
        if (ok) {
          dp[i][nst] += v;
          if (dp[i][nst] >= M) dp[i][nst] -= M;
        }
      }
    }
  }

  LL ans = 0;
  rep(st, lim) {
    LL v = dp[N-1][st];
    rep(d, 4) { 
      Mat con(4, VC(4, 0));

      rep(u, 4) {
        rep(v, 4) {
          if (u == v) continue;
          con[u][v] = CanReach(st, u, v);
        }
      }

      rep(k, 2) {
        bool dir = d >> k & 1;
        con[k][2+k] |= dir;
        con[2+k][k] |= !dir;
      }
      con = Warshal(con);

      if (!HasLoop(con)) {
        ans += v;
        if (ans >= M) ans -= M;
      }
    }
  }
  printf("%lld\n", ans);
}
accuracy: 1
time_ms: 120
memory_kb: 35456
final_rank: 15

code_snippet: #include<bits/stdc++.h>
#define X first
#define Y second
#define pb emplace_back
#define FOR(i,a,b) for(int (i)=(a);i<(b);++(i))
#define EFOR(i,a,b) for(int (i)=(a);i<=(b);++(i))
#define rep(X,Y) for (int (X) = 0;(X) < (Y);++(X))
#define reps(X,S,Y) for (int (X) = S;(X) < (Y);++(X))
#define rrep(X,Y) for (int (X) = (Y)-1;(X) >=0;--(X))
#define rreps(X,S,Y) for (int (X) = (Y)-1;(X) >= (S);--(X))
#define all(X) (X).begin(),(X).end()
#define rall(X) (X).rbegin(),(X).rend()
#define eb emplace_back
#define UNIQUE(X) (X).erase(unique(all(X)),(X).end())

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef ll LL;
typedef pii PII;
typedef pll PLL;
template<class T> using vv=vector<vector<T>>;
template<class T> inline bool MX(T &l,const T &r){return l<r?l=r,1:0;}
template<class T> inline bool MN(T &l,const T &r){return l>r?l=r,1:0;}

int N;
LL M;
int ord[4][4];
LL dp[1145][1 << 13];

// u -> v
bool CanReach(int st, int u, int v) {
   int idx = ord[u][v];
   return st >> idx & 1;
}

void Set(int &nst, int u, int v, bool b) {
  int idx = ord[u][v];
  if (b) nst |= 1 << idx;
  else nst &= ~(1 << idx);
}

void Add(int &nst, int u, int v, bool b) {
  if (!b) return;

  int idx = ord[u][v];
  nst |= 1 << idx;
}

using VC = vector<char>;
using Mat = vector<VC>;

Mat Warshal(Mat &src) {
  int m = src.size();
  Mat ret(src);

  rep(w, m) {
    rep(u, m) {
      rep(v, m) {
        ret[u][v] |= ret[u][w] & ret[w][v];
      }
    }
  }
  return move(ret);
}

int Statize(Mat &src) {
  int ret = 0;
  rep(u, 4) {
    rep(v, 4) {
      if (u == v) continue;
      if (!src[u][v]) continue;
      int idx = ord[u][v];
      ret |= 1 << idx;
    }
  }
  return ret;
}

int memo2[1 << 12][8];
int memo[1 << 12][8];
pii NxtSt(int st, int d) {
  if (memo[st][d] >= 0) return pii(memo[st][d], memo2[st][d]);

  Mat con(6, VC(6, 0));
  rep(u, 4) {
    rep(v, 4) {
      if (u == v) continue;
      con[u][v] = CanReach(st, u, v);
    }
  }

  rep(k, 2) {
    bool dir = d >> k & 1;
    con[2+k][4+k] = dir;
    con[4+k][2+k] = !dir;
  }

  bool dir = d >> 2 & 1;
  con[4][5] = dir;
  con[5][4] = !dir;
  con = Warshal(con);

  int nst = 0;
  int vs[] = {0, 1, 4, 5};
  rep(i, 4) {
    int u = vs[i];
    rep(j, 4) {
      if (i == j) continue;

      int v = vs[j];
      Set(nst, i, j, con[u][v]);
    }
  }

  int loop = 0;
  rep(v, 6) {
    loop |= con[v][v];
  }
  memo2[st][d] = !loop;
  memo[st][d] = nst;
  return pii(nst, !loop);
}

int main() {
  {
    int cnt = 0;
    rep(u, 4) {
      rep(v, 4) {
        if (u == v) continue;
        ord[u][v] = cnt++;
      }
    }
  }
  fill(memo[0], memo[1 << 12], -1);
  fill(memo2[0], memo2[1 << 12], -1);

  scanf("%d%lld", &N, &M);
  
  rep(a, 2) {
    rep(b, 2) {
      rep(c, 2) {
        rep(d, 2) {
          Mat mat(4, VC(4, 0));
          mat[0][1] = a;
          mat[1][0] = !a;
          mat[0][2] = b;
          mat[2][0] = !b;
          mat[1][3] = c;
          mat[3][1] = !c;
          mat[2][3] = d;
          mat[3][2] = !d;
          mat = Warshal(mat);

          bool loop = false;
          rep(v, 4) {
            loop |= mat[v][v];
          }
          if (!loop) dp[1][Statize(mat)] = 1;
        }
      }
    }
  }

  int lim = 1 << 12;
  reps(i, 2, N) {
    rep(st, lim) {
      LL v = dp[i-1][st];
      rep(d, 8) { // dirs
        int nst;
        int ok;
        tie(nst, ok) = NxtSt(st, d);
        if (ok) {
          dp[i][nst] += v;
          if (dp[i][nst] >= M) dp[i][nst] -= M;
        }
      }
    }
  }

  LL ans = 0;
  rep(st, lim) {
    LL v = dp[N-1][st];
    rep(d, 4) { 
      Mat con(4, VC(4, 0));

      rep(u, 4) {
        rep(v, 4) {
          if (u == v) continue;
          con[u][v] = CanReach(st, u, v);
        }
      }

      rep(k, 2) {
        bool dir = d >> k & 1;
        con[k][2+k] |= dir;
        con[2+k][k] |= !dir;
      }
      con = Warshal(con);

      bool loop = false;
      rep(v, 4) {
        loop |= con[v][v];
      }
      if (!loop) {
        ans += v;
        if (ans >= M) ans -= M;
      }
    }
  }
  printf("%lld\n", ans);
}
accuracy: 1
time_ms: 120
memory_kb: 35408
final_rank: 14

code_snippet: #include <bits/stdc++.h>
#define syosu(x) fixed<<setprecision(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
typedef pair<double,double> pdd;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<string> vs;
typedef vector<P> vp;
typedef vector<vp> vvp;
typedef vector<pll> vpll;
typedef pair<int,P> pip;
typedef vector<pip> vip;
const int inf=1<<30;
const ll INF=1ll<<60;
const double pi=acos(-1);
const double eps=1e-9;
//const ll mod=1e9+7;
const int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};

int n,mod;
vi dp(4096);

int main(){
	cin>>n>>mod;
	for(int j=0;j<4096;j++){
		int a=j%2,b=j/2%2,c=j/4%2,d=j/8%2,e=j/16%2,f=j/32%2,g=j/64%2,h=j/128%2,x=j/256%2,y=j/512%2,z=j/1024%2,t=j/2048%2;
		if(x!=t) continue;
		if(x==0&&a==1&&b==1&&c==0&&d==1&&e==1&&f==0&&g==1&&h==1) dp[j]++;
		if(x==1&&a==1&&b==0&&c==1&&d==1&&e==1&&f==1&&g==0&&h==1) dp[j]++;
	}
	for(int i=1;i<n;i++){
		vi DP(4096);
		for(int j=0;j<4096;j++) for(int k=0;k<8;k++){
			int a=j%2,b=j/2%2,c=j/4%2,d=j/8%2,e=j/16%2,f=j/32%2,g=j/64%2,h=j/128%2,x=j/256%2,y=j/512%2,z=j/1024%2,t=j/2048%2;
			int A=0,B=0,C=0,D=0,E=0,F=0,G=0,H=0,X=k%2,Y=k/2%2,Z=k/4%2;
			if(x==0&&y==0&&z==0&&X==1||x==1&&y==1&&z==1&&X==0) continue;
			if(a==1&&y==1) A=1;
			if(b==1&&z==0) B=1;
			if(A==1&&X==0) B=1;
			if(B==1&&X==1) A=1;
			if(c==1&&y==1) C=1;
			if(d==1&&z==0) D=1;
			if(C==1&&X==0) D=1;
			if(D==1&&X==1) C=1;
			if(e==1&&y==0) E=1;
			if(f==1&&z==1) F=1;
			if(E==1&&X==1) F=1;
			if(F==1&&X==0) E=1;
			if(g==1&&y==0) G=1;
			if(h==1&&z==1) H=1;
			if(G==1&&X==1) H=1;
			if(H==1&&X==0) G=1;
			if(i==n-1){
				if(A==1&&Y==1||B==1&&Z==0&&t==1) continue;
				if(D==1&&Z==0||C==1&&Y==1&&t==0) continue;
				if(E==1&&Y==0||F==1&&Z==1&&t==0) continue;
				if(H==1&&Z==1||G==1&&Y==0&&t==1) continue;
				if(X==0&&Y==0&&Z==0&&t==1) continue;
				if(X==1&&Y==1&&Z==1&&t==0) continue;
			}
			(DP[A+B*2+C*4+D*8+E*16+F*32+G*64+H*128+X*256+Y*512+Z*1024+t*2048]+=dp[j])%=mod;
		}
		dp=DP;
	}
	int res=0;
	for(auto i:dp) (res+=i)%=mod;
	cout<<res<<endl;
}
accuracy: 1
time_ms: 260
memory_kb: 3200
final_rank: 7

code_snippet: // vvvvvvvvvvvv TEMPLATE vvvvvvvvvvvv
#include <bits/stdc++.h>
using namespace std; using ll = long long; using P = pair<ll, ll>;
const ll linf = 1e18; const double eps = 1e-12, pi = acos(-1);
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define each(i,a) for (auto&& i : a)
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define eb emplace_back
#define all(a) begin(a),end(a)
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)
#define min(x,y) (x < y ? x : y)
#define max(x,y) (x < y ? y : x)
template<typename Head> void out(Head h) { cout << h << endl; } template<typename Head, typename... Tail>void out(Head h, Tail... t) { cout << h << " "; out(t...); }
template<typename T> istream& operator>>(istream& is, vector<T>& v) { each(x,v) is >> x; return is; }
template<typename T> ostream& operator<<(ostream& os, const vector<T>& v) { rep(i,v.size()) { if (i) os << " "; os << v[i]; } return os; }
template<typename T> ostream& operator<<(ostream& os, const vector<string>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
template<typename T> ostream& operator<<(ostream& os, const vector<vector<T>>& v) { rep(i,v.size()) { if (i) os << endl; os << v[i]; } return os; }
struct yes_no : std::numpunct<char> { string_type do_truename() const { return "Yes"; } string_type do_falsename() const { return "No"; } };
void solve(); int main() {
  ios::sync_with_stdio(false); cin.tie(0); locale loc(locale(), new yes_no); cout.imbue(loc); cout << fixed << setprecision(10) << boolalpha;
  solve();
}
// ^^^^^^^^^^^^ TEMPLATE ^^^^^^^^^^^^

ll mod = 1e9+7;
ll mul(ll a, ll b) { return a * b % mod; }
ll mul(initializer_list<ll> t) { ll res = 1; each(v, t) res = mul(res, v); return res; }
ll add(ll a, ll b) { return (a + b) % mod; }
ll add(initializer_list<ll> t) { ll res = 0; each(v, t) res = add(res, v); return res; }
ll sub(ll a, ll b) { return (a - b + mod) % mod; }
ll sub(initializer_list<ll> t) { auto it = t.begin(); ll res = *(it++); while (it != t.end()) res = sub(res, *(it++)); return res; }
ll inv(ll n); ll power(ll x, ll n) { if (n < 0) return inv(power(x, -n)); ll res = 1; for (ll i = 1; i <= n; i <<= 1) { if (i & n) res = mul(res, x); x = mul(x, x); } return res; }
ll inv(ll n) { return power(n, mod-2); }
ll divi(ll a, ll b) { return mul(a, inv(b)); }
ll divi(initializer_list<ll> t) { auto it = t.begin(); ll res = *(it++); while (it != t.end()) res = divi(res, *(it++)); return res; }
// template<size_t n> struct Fact { ll fact[n+1]; public: constexpr Fact() : fact() { fact[0] = 1; rep(i, 1, n+1) fact[i] = fact[i-1] * i % mod; } ll operator[](size_t idx) const { return fact[idx]; } };
// constexpr auto fact = Fact<size_t(300000)>();
// ll comb(ll n, ll r) { if (r < 0) return 0; if (r > n) return 0; return divi(fact[n], mul(fact[r], fact[n-r])); }

using Row = vector<ll>;
using Matrix = vector<Row>;
Matrix E(ll n) { Matrix res(n, Row(n, 0)); rep(i, n) res[i][i] = 1; return res; }
Matrix mul(const Matrix& A, const Matrix& B) { const ll n = A.size(), m = A[0].size(), l = B[0].size(); assert(m == B.size()); Matrix res(n, Row(l, 0)); rep(i, n) rep(j, m) rep(k, l) res[i][k] = add(res[i][k], mul(A[i][j], B[j][k])); return res; }
Row mul(const Matrix& A, const Row& x) { Matrix tx(x.size()); rep(i, x.size()) tx[i] = Row(1, x[i]); tx = mul(A, tx); Row res(x.size()); rep(i, x.size()) res[i] = tx[i][0]; return res; }
Matrix power(Matrix A, ll n) { assert(A.size() == A[0].size()); Matrix res = E(A.size()); for (ll i = 1; i <= n; i <<= 1) { if (i & n) res = mul(res, A); A = mul(A, A); } return res; }

using Graph = array<array<ll, 4>, 4>;

void output_graph(const Graph& g) {
  cout << "┌┐";
  if (g[0][1]) {
    cout << "─→";
  }
  else {
    cout << "    ";
  }
  cout << "┌┐" << endl;

  cout << "└┘";
  if (g[1][0]) {
    cout << "←─";
  }
  else {
    cout << "    ";
  }
  cout << "└┘" << endl;

  if (g[0][2]) cout << "│";
  else cout << "  ";
  if (g[2][0]) cout << "↑";
  else cout << "  ";

  if (g[0][3]) cout << "↘";
  else cout << "  ";
  if (g[1][2]) cout << "↙";
  else cout << "  ";

  if (g[1][3]) cout << "│";
  else cout << "  ";
  if (g[3][1]) cout << "↑";
  else cout << "  ";
  cout << endl;

  if (g[0][2]) cout << "↓";
  else cout << "  ";
  if (g[2][0]) cout << "│";
  else cout << "  ";

  if (g[2][1]) cout << "↗";
  else cout << "  ";
  if (g[3][0]) cout << "↖";
  else cout << "  ";

  if (g[1][3]) cout << "↓";
  else cout << "  ";
  if (g[3][1]) cout << "│";
  else cout << "  ";
  cout << endl;

  cout << "┌┐";
  if (g[2][3]) {
    cout << "─→";
  }
  else {
    cout << "    ";
  }
  cout << "┌┐" << endl;

  cout << "└┘";
  if (g[3][2]) {
    cout << "←─";
  }
  else {
    cout << "    ";
  }
  cout << "└┘" << endl;
}

template<size_t N>
ostream& operator<<(ostream& os, const array<array<ll, N>, N>& g) {
  rep(i, g.size()) {
    rep(j, g[0].size()) {
      if (j) os << " ";
      os << (g[i][j] ? 1 : 0);
    }
    os << endl;
  }
  return os;
}

struct Edge {
  ll a, b;
};

Graph G0 = {};
ll M1, M2 = 1LL<<3;
vector<Edge> edges1, edges2;

Graph get_graph1(ll hash) {
  Graph res = G0;
  rep(i, edges1.size()) {
    if (hash>>i & 1) {
      const Edge& e = edges1[i];
      res[e.a][e.b] = true;
    }
  }
  return res;
}
Graph get_graph2(ll hash) {
  Graph res = G0;
  rep(i, edges2.size()) {
    const Edge& e = edges2[i];
    if (hash>>i & 1) {
      res[e.a][e.b] = true;
    }
    else {
      res[e.b][e.a] = true;
    }
  }
  return res;
}

ll to_hash1(const Graph& g, bool force=false) {
  if (!force) {
    rep(u, 4) rep(v, 4) {
      if (u == v) continue;
      if (g[u][v] && g[v][u]) {
        return -1;
      }
    }
  }
  ll res = 0;
  rep(i, edges1.size()) {
    const Edge& e = edges1[i];
    if (g[e.a][e.b]) {
      res += 1LL<<i;
    }
  }
  return res;
}

Graph merge_graph(const Graph& g1, const Graph& g2) {
  array<array<ll, 6>, 6> G{};
  rep(i, 6) G[i][i] = true;
  rep(u, 4) rep(v, 4) {
    if (g1[u][v]) G[u+2][v+2] = true;
    if (g2[u][v]) G[u][v] = true;
  }
  rep(k, 6) rep(i, 6) rep(j, 6) {
    if (G[i][k] && G[k][j]) {
      G[i][j] = true;
    }
  }
  array<ll, 4> ord{0, 1, 4, 5};
  Graph g = G0;
  rep(u, 4) rep(v, 4) {
    g[u][v] = G[ord[u]][ord[v]];
  }
  return g;
}

void init_edges() {
  rep(i, 4) rep(j, 4) {
    if (i == j) continue;
    edges1.pb({i, j});
  }
  edges2.pb({0, 1});
  edges2.pb({0, 2});
  edges2.pb({1, 3});
}


void solve() {
  ll n; cin >> n >> mod;
  rep(i, 4) G0[i][i] = true;
  init_edges();
  M1 = 1LL<<edges1.size();
  assert(edges1.size() == 12);
  // {
  //   Graph g1 = G0;
  //   Graph g2 = G0;
  //   g1[1][0] = true;
  //   g2[2][0] = true;
  //   g2[0][1] = true;
  //   g2[1][3] = true;
  //   output_graph(g2);
  //   output_graph(g1);
  //   Graph g = merge_graph(g1, g2);
  //   output_graph(g);
  //   cout << to_hash1(g) << endl;
  // }
  // return;
  vector<vector<ll>> merged(M1, vector<ll>(M2));
  rep(i, M1) rep(j, M2) {
    Graph g1 = get_graph1(i);
    Graph g2 = get_graph2(j);
    Graph g = merge_graph(g1, g2);
    merged[i][j] = to_hash1(g);
  }
  // rep(i, M1) {
  //   assert(to_hash1(get_graph1(i), true) == i);
  // }
  // cout << M2 << endl;
  // rep(i, M2) {
  //   output_graph(get_graph2(i));
  // }
  Graph g0 = G0;
  g0[0][2] = g0[2][0] = true;
  g0[1][3] = g0[3][1] = true;
  vector<vector<ll>> dp(n+1, vector<ll>(M1, 0));
  dp[0][to_hash1(g0, true)] = 1;
  rep(i, n) rep(j, M1) {
    if (dp[i][j] == 0) continue;
    rep(k, M2) {
      ll nj = merged[j][k];
      if (nj < 0) continue;
      dp[i+1][nj] = add(dp[i][j], dp[i+1][nj]);
    }
  }
  ll ans = 0;
  rep(i, M1) {
    Graph g = get_graph1(i);
    array<array<ll, 2>, 2> G{};
    rep(j, 4) rep(k, 4) {
      if (g[j][k]) G[j%2][k%2] = true;
    }
    if (g[0][2] || g[2][0] || g[1][3] || g[3][1]) continue;
    if (G[0][1] && G[1][0]) continue;
    if (dp[n][i] == 0) continue;
    // cout << dp[n][i] << endl;
    // output_graph(g);
    // cout << endl;
    ans = add(ans, dp[n][i]);
  }
  cout << ans << endl;
}
accuracy: 1
time_ms: 20
memory_kb: 35360
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

typedef int _loop_int;
#define REP(i,n) for(_loop_int i=0;i<(_loop_int)(n);++i)
#define FOR(i,a,b) for(_loop_int i=(_loop_int)(a);i<(_loop_int)(b);++i)
#define FORR(i,a,b) for(_loop_int i=(_loop_int)(b)-1;i>=(_loop_int)(a);--i)

#define DEBUG(x) cout<<#x<<": "<<x<<endl
#define DEBUG_VEC(v) cout<<#v<<":";REP(i,v.size())cout<<" "<<v[i];cout<<endl
#define ALL(a) (a).begin(),(a).end()

#define CHMIN(a,b) a=min((a),(b))
#define CHMAX(a,b) a=max((a),(b))

int n,m;

// first UD
// before UD
// 0-start right ongoing loop at up
// 0-start right ongoing loop at down
// 0-start left ongoing loop at up
// 0-start left ongoing loop at down
// 1-start right ongoing loop at up
// 1-start right ongoing loop at down
// 1-start left ongoing loop at up
// 1-start left ongoing loop at down
// 2^10 !?
ll dp[1252][1024];

int f(int a,int b,int c,int d,int e,int f,int g,int h,int i,int j){
  int ret = 0;
  ret |= a<<0;
  ret |= b<<1;
  ret |= c<<2;
  ret |= d<<3;
  ret |= e<<4;
  ret |= f<<5;
  ret |= g<<6;
  ret |= h<<7;
  ret |= i<<8;
  ret |= j<<9;
  return ret;
}

int main(){
  scanf("%d%d",&n,&m);
  dp[0][f(0,0, 1,1,1,0, 0,1,1,1)] = 1;
  dp[0][f(1,1, 1,0,1,1, 1,1,0,1)] = 1;
  int te = 0;
  REP(i,n)REP(state,1024){
    REP(ud,2)REP(uprl,2)REP(dorl,2){
      int first = state>>0&1;
      int before = state>>1&1;
      int usru = state>>2&1;
      int usrd = state>>3&1;
      int uslu = state>>4&1;
      int usld = state>>5&1;
      int dsru = state>>6&1;
      int dsrd = state>>7&1;
      int dslu = state>>8&1;
      int dsld = state>>9&1;
      if(i==n-1){
        if(first != ud)continue;
      }
      if(before && uprl && !ud && !dorl)continue;
      if(!before && !uprl && ud && dorl)continue;
      int nfirst = first;
      int nbefore = ud;
      int nusru = (usru && uprl) || (usrd && dorl && ud);
      int nusrd = (usru && uprl && !ud) || (usrd && dorl);
      int nuslu = (uslu && !uprl) || (usld && !ud && !dorl);
      int nusld = (uslu && ud && !uprl) || (usld && !dorl);
      int ndsru = (dsru && uprl) || (dsrd && ud && dorl);
      int ndsrd = (dsru && !ud && uprl) || (dsrd && dorl);
      int ndslu = (dslu && !uprl) || (dsld && !ud && !dorl);
      int ndsld = (dslu && ud && !uprl) || (dsld && !dorl);
      // if(i==n-1 && dp[i][state] > 0){
      //   printf("%d %d: %lld\n",i,state,dp[i][state]);
      //   te += dp[i][state];
      // }
      if(i==n-1){
        if(nusru || nuslu || ndsrd || ndsld)continue;
      }
      int nstate = f(nfirst,nbefore,nusru,nusrd,nuslu,nusld,ndsru,ndsrd,ndslu,ndsld);
      (dp[i+1][nstate] += dp[i][state]) %= m;
    }
  }
  // DEBUG(te);
  ll ans = 0;
  REP(state,1024){
    ans += dp[n][state];
    ans %= m;
  }
  printf("%lld\n",ans);
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 11136
final_rank: 5

code_snippet: // ちょっと重めの解法

#include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
#include <cassert>
using namespace std;
using lint = long long int;
using Mat = vector< vector<int> >;

void alloc(Mat &mat, int H, int W) {
    int D = mat.size();
    assert(D <= H and D <= W);
    for(int i=0; i<D; i++) {
        mat[i].resize(W);
    }
    for(int i=D; i<H; i++) {
        mat.push_back(vector<int>(W));
    }
}

void run_wf(Mat &mat, int u, int v) {
    int D = mat.size();
    mat[u][v] = 1;
    for(int i=0; i<D; i++) {
        for(int j=0; j<D; j++) {
            int bu = (i == u ? 1 : mat[i][u]);
            int bv = (v == j ? 1 : mat[v][j]);
            mat[i][j] |= (bu & bv);
        }
    }
}

void dump_mat(Mat &mat) {
    int D = mat.size();
    for(int i=0; i<D; i++) {
        for(int j=0; j<D; j++) {
            fprintf(stderr, "%d ", mat[i][j]);
        }
        fprintf(stderr, "\n");
    }
}

Mat clean_mat(Mat &mat) {
    Mat res;
    int D = mat.size();
    assert(D == 6);
    alloc(res, D-2, D-2);

    for(int i=0; i<D; i++) {
        for(int j=0; j<D; j++) {
            if(D-4 <= i and i <= D-3) continue;
            if(D-4 <= j and j <= D-3) continue;
            int ii = (i < D-4 ? i : i-2);
            int jj = (j < D-4 ? j : j-2);
            res[ii][jj] = mat[i][j];
        }
    }
    return res;
}

lint N, MOD;
int main() {
    scanf("%lld%lld", &N, &MOD);

    // 最初の状態 (2 つ)
    Mat mat1, mat2;
    alloc(mat1, 2, 2);
    alloc(mat2, 2, 2);
    mat1[0][1] = 1;
    mat2[1][0] = 1;

    map<Mat, int> dp;
    dp[mat1] = 1;
    dp[mat2] = 1;
    for(int i=0; i<N; i++) {
        map<Mat, int> nxt;
        for(auto &e : dp) {
            Mat mat = e.first; lint val = e.second;
            // 新たに 3 辺追加される
            // その向きづけを全部試す感じ？
            int D = mat.size();

            // 最後以外
            if(i < N-1) {
                alloc(mat, D+2, D+2);
                for(int bit=0; bit<(1<<3); bit++) {
                    Mat cand = mat;
                    (bit >> 0 & 1) ? run_wf(cand, D  , D-2) : run_wf(cand, D-2, D  );
                    (bit >> 1 & 1) ? run_wf(cand, D+1, D-1) : run_wf(cand, D-1, D+1);
                    (bit >> 2 & 1) ? run_wf(cand, D  , D+1) : run_wf(cand, D+1, D  );
                    bool ok = true;
                    for(int k=0; k<D+2; k++) {
                        ok &= (cand[k][k] == 0);
                    }
                    
                    if(ok) {
                        // 最初以外は、D-2, D-1 (行, 列) 目はいらない
                        Mat put_mat;
                        if(i > 0) {
                            put_mat = clean_mat(cand);
                        }
                        else {
                            put_mat = cand;
                        }
                        (nxt[put_mat] += val) %= MOD;
                    }
                }
            }
            // 最後
            else {
                for(int bit=0; bit<(1<<2); bit++) {
                    Mat cand = mat;
                    (bit >> 0 & 1) ? run_wf(cand, D-2, 0  ) : run_wf(cand, 0  , D-2);
                    (bit >> 1 & 1) ? run_wf(cand, D-1, 1  ) : run_wf(cand, 1  , D-1);
                    bool ok = true;
                    for(int k=0; k<D; k++) {
                        ok &= (cand[k][k] == 0);
                    }

                    if(ok) {
                        (nxt[cand] += val) %= MOD;
                    }
                }
            }
        }
        swap(dp, nxt);
    }

    lint ans = 0;
    for(auto &e : dp) (ans += e.second) %= MOD;
    printf("%lld\n", ans);
    return 0;
}
accuracy: 1
time_ms: 270
memory_kb: 2896
final_rank: 8

code_snippet: // メモ化などをして少し速くしたやつ

#include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
#include <unordered_map>
using namespace std;
using lint = long long int;

const int SIZE = 4;
lint dp[2][1 << 16], expand[3][1 << 16];
const int width[] = {2, 4, 6};
unordered_map<lint, lint> to[3], cleaned;

void mod_add(lint &A, lint &B, lint &MOD) {
    A += B;
    if(A >= MOD) A -= MOD;
}

int get_idx(int r, int c, int w) { return r*w + c; }

// width[id]*width[id] の行列サイズを 2 増やす
// 増やすを bit pattern がずれるのでその調整
// 2*2 または 4*4 が考えられる
lint get_expanded_bit(lint bit, int id) {
    if(expand[id][bit] >= 0) return expand[id][bit];

    int w = width[id], shift = 0;
    lint res = 0, orig = bit;
    for(int i=0; i<w; i++) {
        lint pat = bit & ((1LL << w) - 1);
        res |= (pat << shift);
        bit >>= w;
        shift += w + 2;
    }
    return expand[id][orig] = res;
}

// w*w 行列のワーシャルフロイド
// 4*4 または 6*6 が考えられる
void run_wf(lint &bit, int x, int y, int id) {
    int w = width[id];
    bit |= (1LL << get_idx(x, y, w));
    if(to[id].count(bit)) {
        bit = to[id][bit];
        return;
    }

    lint orig = bit;
    for(int i=0; i<w; i++) {
        for(int j=0; j<w; j++) {
            lint bu = (i == x ? 1 : (bit >> get_idx(i, x, w) & 1));
            lint bv = (y == j ? 1 : (bit >> get_idx(y, j, w) & 1));
            bit |= ((bu & bv) << get_idx(i, j, w));
        }
    }
    to[id][orig] = bit;
}

// 6*6 を 4*4 に直す (ここには 6*6 しか来ない)
// メモ化しないほうが速い説ありそう (適当)
lint clean_bit(lint bit) {
    // if(cleaned.count(bit)) return cleaned[bit];

    lint res = 0, shift = 0;
    const int w = 2;
    for(int i=0; i<6; i++) {
        if(2 <= i and i <= 3) {
            bit >>= 6;
        }
        else {
            lint bitL = bit & ((1LL << w) - 1);
            bit >>= 4;
            lint bitR = bit & ((1LL << w) - 1);
            bit >>= 2;
            
            lint add = bitL | (bitR << w);
            res |= (add << shift);
            shift += 4;
        }
    }

    return cleaned[bit] = res;
}

int main() {
    fill(expand[0], expand[2], -1);
    lint N, MOD; scanf("%lld%lld", &N, &MOD);
    dp[0][1 << get_idx(1, 0, 2)] = dp[0][1 << get_idx(0, 1, 2)] = 1;

    // 4*4 行列のダメなパターンと、6*6 行列のダメなパターン
    lint ng_bit_4 = 0, ng_bit_6 = 0;
    for(int i=0; i<6; i++) {
        if(i < 4) ng_bit_4 |= (1LL << get_idx(i, i, 4));
        ng_bit_6 |= (1LL << get_idx(i, i, 6));
    }
    
    for(int i=0; i<N; i++) {
        int cur = i%2, nxt = 1 - cur;
        for(lint mask=0; mask<(1<<16); mask++) {
            if(dp[cur][mask] == 0) continue;
            if(i < N-1) {
                // i == 0: 2*2 -> 4*4
                // i  > 0: 4*4 -> 6*6 -> 4*4
                const int D = (i == 0 ? 2 : 4);
                const int id = (i == 0 ? 1 : 2);
                for(int bit=0; bit<(1<<3); bit++) {
                    lint cand = get_expanded_bit(mask, i > 0);
                    lint ng_bit = (D == 2 ? ng_bit_4 : ng_bit_6);
                    (bit >> 0 & 1) ? run_wf(cand, D  , D-2, id) : run_wf(cand, D-2, D  , id);
                    if((cand & ng_bit) > 0) continue;
                    (bit >> 1 & 1) ? run_wf(cand, D+1, D-1, id) : run_wf(cand, D-1, D+1, id);
                    if((cand & ng_bit) > 0) continue;
                    (bit >> 2 & 1) ? run_wf(cand, D  , D+1, id) : run_wf(cand, D+1, D  , id);
                    if((cand & ng_bit) > 0) continue;
                    
                    lint put_bit;
                    if(i > 0) put_bit = clean_bit(cand);
                    else put_bit = cand;
                    mod_add(dp[nxt][put_bit], dp[cur][mask], MOD);
                }
            }
            else {
                // 4*4 -> 4*4
                const int D = 4;
                const int id = 1;
                for(int bit=0; bit<(1<<2); bit++) {
                    lint cand = mask;
                    lint ng_bit = ng_bit_4;
                    (bit >> 0 & 1) ? run_wf(cand, D-2, 0  , id) : run_wf(cand, 0  , D-2, id);
                    if((cand & ng_bit) > 0) continue;
                    (bit >> 1 & 1) ? run_wf(cand, D-1, 1  , id) : run_wf(cand, 1  , D-1, id);
                    if((cand & ng_bit) > 0) continue;

                    mod_add(dp[nxt][cand], dp[cur][mask], MOD);
                }
            }
            dp[cur][mask] = 0;
        }
    }

    lint ans = 0, pari = N%2;
    for(int mask=0; mask<(1<<16); mask++) {
        if(dp[pari][mask] == 0) continue;
        mod_add(ans, dp[pari][mask], MOD);
    }
    printf("%lld\n", ans);
    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3900
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <map>
using namespace std;

int MOD;
void modAdd(int& a, int b) { a = (a + b) % MOD; }

int getShift(int u, int v) { return  u * 4 + v; }
int getEraseMask(int u, int v) { return ((1 << 16) - 1) ^ (1 << getShift(u, v)); }

bool isReachable(const int state, int s, int t) { return state >> getShift(s, t) & 1; }

bool hasCycle(const int state) {
	for (int v=0; v<4; ++v) if (isReachable(state, v, v)) return true;
	return false;
}

void addArc(int& state, int u, int v) { // add arc (u,v)
	vector< int > src, dst;
	for (int s=0; s<4; ++s) if (s == u || isReachable(state, s, u)) src.push_back(s);
	for (int t=0; t<4; ++t) if (t == v || isReachable(state, v, t)) dst.push_back(t);	
	for (int s : src) for (int t : dst) state |= (1 << getShift(s, t));
}

void eraseRow(int& state, int u) { for (int v=0; v<4; ++v) state &= getEraseMask(u, v); }
void eraseCol(int& state, int v) { for (int u=0; u<4; ++u) state &= getEraseMask(u, v); }

int rec(const int i, const int N, int state, vector< map< int, int > >& memo) {
	if (i == N) return 1;
	
	if (memo[i].count(state)) return memo[i][state];
	
	int ret = 0;
	
	for (int S=0; S<8; ++S) { // 000 ~ 111, ({2i, 2i+1}, {2i, 2i+2}, {2i+1, 2i+3})
		int nxt_state = state;
		
		if (i == 0) {
			if (S & 1) addArc(nxt_state, 0, 1);	// add (2i, 2i+1)
			else addArc(nxt_state, 1, 0);		// add (2i+1, 2i)
			
			if (S & 2) addArc(nxt_state, 2, 0);	// add (2i, 2i+2)
			else addArc(nxt_state, 0, 2);		// add (2i+2, 2i)
			
			if (S & 4) addArc(nxt_state, 3, 1);	// add (2i, 2i+3)
			else addArc(nxt_state, 1, 3);		// add (2i+3, 2i)
		}
		else if (i == N-1) {
			if (S & 1) addArc(nxt_state, 2, 3);	// add (2i, 2i+1)
			else addArc(nxt_state, 3, 2);		// add (2i+1, 2i)
			
			if (S & 2) addArc(nxt_state, 2, 0);	// add (2i, 2i+2)
			else addArc(nxt_state, 0, 2);		// add (2i+2, 2i)
			
			if (S & 4) addArc(nxt_state, 3, 1);	// add (2i, 2i+3)
			else addArc(nxt_state, 1, 3);		// add (2i+3, 2i)
			
			if (hasCycle(nxt_state)) continue;	// cycle check
		}
		else {
			if (S & 1) addArc(nxt_state, 2, 3);	// add (2i, 2i+1)
			else addArc(nxt_state, 3, 2);		// add (2i+1, 2i)
			
			if (hasCycle(nxt_state)) continue;	// cycle check
			
			if (S & 2) eraseRow(nxt_state, 2);	// add (2i, 2i+2)
			else eraseCol(nxt_state, 2);		// add (2i+2, 2i)
			
			if (S & 4) eraseRow(nxt_state, 3);	// add (2i, 2i+3)
			else eraseCol(nxt_state, 3);		// add (2i+3, 2i)
		}
		
		modAdd(ret, rec(i+1, N, nxt_state, memo));
	}
	
	return memo[i][state] = ret;
}

int main() {
	int N;
	cin >> N >> MOD;
	vector< map< int, int > > memo(N, map< int, int >());
	cout << rec(0, N, 0, memo) << endl;
}
accuracy: 1
time_ms: 50
memory_kb: 5924
final_rank: 1

code_snippet: #include <cstdio>
#include <vector>
#include <algorithm>
#include <map>
#include <cassert>
using namespace std;
using lint = long long int;
using Mat = vector< vector<int> >;

void alloc(Mat &mat, int H, int W) {
    int D = mat.size();
    assert(D <= H and D <= W);
    for(int i=0; i<D; i++) {
        mat[i].resize(W);
    }
    for(int i=D; i<H; i++) {
        mat.push_back(vector<int>(W));
    }
}

void run_wf(Mat &mat) {
    int D = mat.size();
    for(int k=0; k<D; k++) {
        for(int i=0; i<D; i++) {
            for(int j=0; j<D; j++) {
                mat[i][j] |= (mat[i][k] & mat[k][j]);
            }
        }
    }
}

void dump_mat(Mat &mat) {
    int D = mat.size();
    for(int i=0; i<D; i++) {
        for(int j=0; j<D; j++) {
            fprintf(stderr, "%d ", mat[i][j]);
        }
        fprintf(stderr, "\n");
    }
}

Mat clean_mat(Mat &mat) {
    Mat res;
    int D = mat.size();
    assert(D == 6);
    alloc(res, D-2, D-2);

    for(int i=0; i<D; i++) {
        for(int j=0; j<D; j++) {
            if(D-4 <= i and i <= D-3) continue;
            if(D-4 <= j and j <= D-3) continue;
            int ii = (i < D-4 ? i : i-2);
            int jj = (j < D-4 ? j : j-2);
            res[ii][jj] = mat[i][j];
        }
    }

    /*
    fprintf(stderr, "# mat\n");
    dump_mat(mat);
    fprintf(stderr, "# res\n");
    dump_mat(res);
    */    
    return res;
}

lint N, MOD;
int main() {
    scanf("%lld%lld", &N, &MOD);

    // 最初の状態 (2 つ)
    Mat mat1, mat2;
    alloc(mat1, 2, 2);
    alloc(mat2, 2, 2);
    mat1[0][1] = 1;
    mat2[1][0] = 1;

    map<Mat, int> dp;
    dp[mat1] = 1;
    dp[mat2] = 1;
    for(int i=0; i<N; i++) {
        map<Mat, int> nxt;
        for(auto &e : dp) {
            Mat mat = e.first; lint val = e.second;
            // 新たに 3 辺追加される
            // その向きづけを全部試す感じ？
            int D = mat.size();

            // 最後以外
            if(i < N-1) {
                alloc(mat, D+2, D+2);
                // fprintf(stderr, "resize: D = %lld, H = %zu, W = %zu\n", D, mat.size(), mat[0].size());
                for(int bit=0; bit<(1<<3); bit++) {
                    Mat cand = mat;
                    ((bit >> 0 & 1) ? cand[D  ][D-2] : cand[D-2][D  ]) = 1;
                    ((bit >> 1 & 1) ? cand[D+1][D-1] : cand[D-1][D+1]) = 1;
                    ((bit >> 2 & 1) ? cand[D  ][D+1] : cand[D+1][D  ]) = 1;
                    
                    run_wf(cand);
                    bool ok = true;
                    for(int k=0; k<D+2; k++) {
                        ok &= (cand[k][k] == 0);
                    }
                    
                    if(ok) {
                        // 最初以外は、D-2, D-1 (行, 列) 目はいらない
                        Mat put_mat;
                        if(i > 0) {
                            put_mat = clean_mat(cand);
                        }
                        else {
                            put_mat = cand;
                            // fprintf(stderr, "# mat #\n");
                            // dump_mat(cand);
                        }
                        (nxt[put_mat] += val) %= MOD;
                    }
                }
            }
            // 最後
            else {
                for(int bit=0; bit<(1<<2); bit++) {
                    Mat cand = mat;
                    ((bit >> 0 & 1) ? cand[D-2][0  ] : cand[0  ][D-2]) = 1;
                    ((bit >> 1 & 1) ? cand[D-1][1  ] : cand[1  ][D-1]) = 1;

                    run_wf(cand);
                    bool ok = true;
                    for(int k=0; k<D; k++) {
                        ok &= (cand[k][k] == 0);
                    }

                    if(ok) {
                        (nxt[cand] += val) %= MOD;
                    }
                }
            }
        }
        swap(dp, nxt);
    }

    lint ans = 0;
    for(auto &e : dp) (ans += e.second) %= MOD;
    printf("%lld\n", ans);
    return 0;
}
accuracy: 1
time_ms: 280
memory_kb: 2880
final_rank: 10