#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;
const int MOD = 1000000007;
const int MAX_N = 15; // Giới hạn an toàn cho Bitmask DP là n <= 12
vector<vector<int>> INDEP;
long long memoH[MAX_N + 1];
long long memoF[MAX_N + 1][MAX_N + 1];
long long memoR[MAX_N + 1][MAX_N + 1];
// Tính lũy thừa a^b % MOD
long long power(long long base, long long exp) {
long long res = 1;
base %= MOD;
while (exp > 0) {
if (exp % 2 == 1) res = (res * base) % MOD;
base = (base * base) % MOD;
exp /= 2;
}
return res;
}
// Khởi tạo các trạng thái Bitmask (Tập độc lập) không có 2 bit 1 kề nhau
void precompute_indep(int n) {
int max_L = 2 * n - 1;
if (max_L < 0) max_L = 0;
INDEP.assign(max_L + 1, vector<int>());
for (int L = 0; L <= max_L; ++L) {
int max_mask = 1 << L;
for (int m = 0; m < max_mask; ++m) {
if ((m & (m << 1)) == 0) {
INDEP[L].push_back(m);
}
}
}
}
// SOS DP: Sum Over Subsets (Zeta Transform)
void subset_sums(vector<int>& out, int L) {
int size = 1 << L;
for (int i = 0; i < L; ++i) {
int step = 1 << i;
int block = step << 1;
for (int start = 0; start < size; start += block) {
int mid = start + step;
int end = start + block;
for (int m = mid; m < end; ++m) {
int s = out[m] + out[m - step];
out[m] = (s >= MOD) ? (s - MOD) : s;
}
}
}
}
// Hàm đếm số cách xếp Lục giác (Tập độc lập) trên lưới DP
int count_independent_sets(const vector<int>& row_lengths) {
if (row_lengths.empty()) return 1;
int L0 = row_lengths[0];
vector<int> dp(1 << L0, 0);
for (int m : INDEP[L0]) {
dp[m] = 1;
}
for (size_t i = 1; i < row_lengths.size(); ++i) {
int Lc = row_lengths[i - 1];
int Ln = row_lengths[i];
vector<int> subs = dp;
subset_sums(subs, Lc); // Biến đổi SOS DP
vector<int> dp2(1 << Ln, 0);
int fullmask = (1 << Lc) - 1;
if (Ln == Lc + 1) {
for (int b : INDEP[Ln]) {
int forb = (b | (b >> 1)) & fullmask;
int allowed = fullmask ^ forb;
dp2[b] = subs[allowed];
}
} else if (Ln == Lc - 1) {
for (int b : INDEP[Ln]) {
int forb = (b | (b << 1)) & fullmask;
int allowed = fullmask ^ forb;
dp2[b] = subs[allowed];
}
}
dp = move(dp2);
}
int last_L = row_lengths.back();
long long total = 0;
for (int m : INDEP[last_L]) {
total = (total + dp[m]) % MOD;
}
return total;
}
// LÕI XANH DƯƠNG: Tính số cách xếp gạch cho Lục giác đều
long long H(int n) {
if (memoH[n] != -1) return memoH[n];
vector<int> lengths;
for (int i = n; i < 2 * n; ++i) lengths.push_back(i);
for (int i = 2 * n - 2; i >= n; --i) lengths.push_back(i);
return memoH[n] = count_independent_sets(lengths);
}
// VÙNG GÓC XANH LÁ: Tính số cách xếp gạch cho góc (Hình thang)
long long F(int n, int h) {
if (memoF[n][h] != -1) return memoF[n][h];
int rows = h - 1;
vector<int> lengths;
for (int i = 0; i < rows; ++i) {
int l = (n - 2) - i;
lengths.push_back(max(0, l));
}
return memoF[n][h] = count_independent_sets(lengths);
}
// ĐỆ QUY CHÍNH: Bóc vỏ dải hình vuông màu cam
long long R(int u, int v) {
if (memoR[u][v] != -1) return memoR[u][v];
if (v == 0) return memoR[u][v] = H(u); // Trúng lõi lục giác
long long res = (u == 1 && v == 1) ? 1 : 0;
for (int w = 0; w < u; ++w) {
long long corner = F(u, u - w);
long long corner6 = power(corner, 6);
res = (res + R(v, w) * corner6) % MOD;
}
return memoR[u][v] = res;
}
// Điểm bắt đầu thuật toán
long long T(int n) {
long long ans = (2 * R(n, n) - (n == 1 ? 1 : 0)) % MOD;
if (ans < 0) ans += MOD; // Xử lý modulo số âm trong C++
return ans;
}
int main() {
// Tối ưu hóa I/O tốc độ cao
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n;
if (cin >> n) {
if (n > 12) {
cout << "Canh bao: n = " << n << " co the vuot qua bo nho hoac chay lau (Time Limit Exceeded)!" << "\n";
}
// Khởi tạo tất cả mảng ghi nhớ (Memoization) bằng -1
memset(memoH, -1, sizeof(memoH));
memset(memoF, -1, sizeof(memoF));
memset(memoR, -1, sizeof(memoR));
// Chuẩn bị các mặt nạ bit (chỉ sinh tới mức n cần thiết để tiết kiệm RAM)
precompute_indep(n);
// Tính và in kết quả
cout << T(n) << "\n";
}
return 0;
}