Problem:
Score : 400 points

Problem Statement

You are given an integer N. Find the number of strings of length N that satisfy the following conditions, modulo 10^9+7:

The string does not contain characters other than A, C, G and T.

The string does not contain AGC as a substring.

The condition above cannot be violated by swapping two adjacent characters once.

Notes

A substring of a string T is a string obtained by removing zero or more characters from the beginning and the end of T.

For example, the substrings of ATCODER include TCO, AT, CODER, ATCODER and (the empty string), but not AC.

Constraints

3 \leq N \leq 100

Input

Input is given from Standard Input in the following format:

N

Output

Print the number of strings of length N that satisfy the following conditions, modulo 10^9+7.

Sample Input 1

3

Sample Output 1

61

There are 4^3 = 64 strings of length 3 that do not contain characters other than A, C, G and T. Among them, only AGC, ACG and GAC violate the condition, so the answer is 64 - 3 = 61.

Sample Input 2

4

Sample Output 2

230

Sample Input 3

100

Sample Output 3

388130742

Be sure to print the number of strings modulo 10^9+7.

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <algorithm>
#include <bitset>
#include <cassert>
#include <chrono>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <map>
#include <queue>
#include <random>
#include <regex>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <sys/timeb.h>
#include <vector>

using namespace std;

#define repr(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rep(i, n) repr(i, 0, n)
#define reprrev(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define reprev(i, n) reprrev(i, 0, n)
#define repi(itr, ds) for (auto itr = ds.begin(); itr != ds.end(); itr++)
#define chmin(mi, val) mi = min(mi, val)
#define chmax(ma, val) ma = max(ma, val)
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define mp make_pair
#define mt make_tuple
#define INF 1050000000
#define INFR INT_MAX
#define INFL (long long)(4e18)
#define INFLR LLONG_MAX
#define EPS (1e-10)
#define MOD 1000000007
//#define MOD 998244353
#define PI 3.141592653589793238
#define RMAX 4294967295

typedef long long ll;
typedef pair< int, int > Pi;
typedef pair< ll, ll > Pll;
typedef pair< double, double > Pd;
typedef vector< int > vi;
typedef vector< ll > vll;
typedef vector< bool > vb;
typedef vector< char > vc;
typedef vector< string > vs;
typedef vector< double > vd;
typedef vector< Pi > vPi;
typedef vector< Pll > vPll;
typedef vector< Pd > vPd;
typedef vector< vector< int > > vvi;
typedef vector< vector< bool > > vvb;
typedef vector< vector< ll > > vvll;
typedef vector< vector< char > > vvc;
typedef vector< vector< string > > vvs;
typedef vector< vector< double > > vvd;
typedef vector< vector< Pi > > vvPi;
typedef vector< vector< vector< int > > > vvvi;
typedef vector< vector< vector< ll > > > vvvll;
typedef vector< vector< vector< Pi > > > vvvPi;
typedef vector< vector< vector< vector< Pi > > > > vvvvPi;
typedef priority_queue< int, vector< int >, greater< int > > pqli;
typedef priority_queue< ll, vector< ll >, greater< ll > > pqlll;
typedef priority_queue< Pi, vector< Pi >, greater< Pi > > pqlP;
template < class T >
using vec = vector< T >;
template < class T >
using pql = priority_queue< T, vector< T >, greater< T > >;

// vvvvvvvvvvvvvvvvvvvvvvv debug output vvvvvvvvvvvvvvvvvvvvvvv
// vector
template < typename T >
istream &operator>>(istream &is, vector< T > &vec) {
    for (T &x : vec) is >> x;
    return is;
}
// pair
template < typename T, typename U >
ostream &operator<<(ostream &os, pair< T, U > &pair_var) {
    os << "(" << pair_var.first << "," << pair_var.second << ")";
    return os;
}
// pair
template < typename T, typename U >
ostream &operator<<(ostream &os, const pair< T, U > &pair_var) {
    os << "(" << pair_var.first << "," << pair_var.second << ")";
    return os;
}
// vector
template < typename T >
ostream &operator<<(ostream &os, const vector< T > &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
// map
template < typename T, typename U >
ostream &operator<<(ostream &os, map< T, U > &map_var) {
    os << "{";
    repi(itr, map_var) {
        os << "(" << itr->first << "," << itr->second << ")";
        itr++;
        if (itr == map_var.end()) os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
// set
template < typename T >
ostream &operator<<(ostream &os, set< T > &set_var) {
    os << "{";
    repi(itr, set_var) {
        os << "  " << *itr << endl;
        itr++;
        if (itr == set_var.end()) os << ", ";
        itr--;
    }
    os << "}";
    return os;
}

#define DUMPOUT cerr

void dump_func() {
    DUMPOUT << endl;
}
template < class Head, class... Tail >
void dump_func(Head &&head, Tail &&... tail) {
    DUMPOUT << head;
    if (sizeof...(Tail) > 0) {
        DUMPOUT << ", ";
    }
    dump_func(std::move(tail)...);
}

#ifdef DEBUG_
#define DEB
#else
#define DEB if (false)
#endif

#ifdef DEBUG_
#define dump(...)                                                              \
    DUMPOUT << "  " << string(#__VA_ARGS__) << ": "                            \
            << "[" << to_string(__LINE__) << ":" << __FUNCTION__ << "]"        \
            << endl                                                            \
            << "    ";                                                         \
    dump_func(__VA_ARGS__)
#else
#define dump(...)
#endif

// ^^^^^^^^^^^^^^^^^^^^^^^ debug output ^^^^^^^^^^^^^^^^^^^^^^^

string YN(bool y, int id = 0) {
    if (id) cout << id;
    return (y ? "YES" : "NO");
}
string yn(bool y, int id = 0) {
    if (id) cout << id;
    return (y ? "Yes" : "No");
}
string ON(bool y, int id = 0) {
    if (id) cout << id;
    return (y ? "OK" : "NG");
}

int dir4[4][2] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}};
int dir8[8][2] = {{-1, -1}, {0, -1}, {1, -1}, {-1, 0},
                  {1, 0},   {-1, 1}, {0, 1},  {1, 1}};
char dirchar[4] = {'<', '^', '>', 'v'};

// [a,b)
int irand(int a, int b) {
    static mt19937 Rand(static_cast< unsigned int >(time(nullptr)));
    uniform_int_distribution< int > dist(a, b - 1);
    return dist(Rand);
}

// [a,b)
double drand(int a, int b) {
    static mt19937 Rand(static_cast< unsigned int >(time(nullptr)));
    uniform_real_distribution< double > dist(a, b);
    return dist(Rand);
}

template < typename T >
T max(vector< T > a) {
    return *max_element(all(a));
}
template < typename T >
T min(vector< T > a) {
    return *min_element(all(a));
}
template < typename T >
T sum(vector< T > a) {
    return accumulate(all(a), (T)0);
}

template < typename T >
void add(map< T, int > &m, T item) {
    if (m.find(item) == m.end()) {
        m[item] = 1;
    } else {
        m[item]++;
    }
}

template < typename T, typename U >
U get(map< T, U > m, T key, U def) {
    if (m.find(key) == m.end()) {
        return def;
    } else {
        return m[key];
    }
}

template < typename T >
bool contains(set< T > t, const T &key) {
    return t.find(key) != t.end();
}

struct Edge {
    int from, to, cost;
    bool operator<(Edge e) {
        return cost < e.cost;
    }
};
using Graph = vec< vec< Edge > >;

ostream &operator<<(ostream &os, Edge &edge) {
    os << "(" << edge.from << "->" << edge.to << ":" << edge.cost << ")";
    return os;
}

//======================================================

template < class T >
vector< T > make_v(size_t size, const T &init) {
    return vector< T >(size, init);
}

template < class... Ts >
auto make_v(size_t size, Ts... rest) {
    return vector< decltype(make_v(rest...)) >(size, make_v(rest...));
}

int main(void) {
    int N;
    cin >> N;
    auto dp = make_v(N + 1, 4, 4, 4, 0);
    dp[0][3][3][3] = 1;
    repr(i, 1, N + 1) {
        rep(a, 4) rep(b, 4) rep(c, 4) rep(d, 4) {
            if (a == 0 && b == 1 && d == 2) continue;
            if (a == 0 && c == 1 && d == 2) continue;
            if (b == 1 && c == 0 && d == 2) continue;
            if (b == 0 && c == 1 && d == 2) continue;
            if (b == 0 && c == 2 && d == 1) continue;
            dp[i][b][c][d] += dp[i - 1][a][b][c];
            dp[i][b][c][d] %= MOD;
        }
    }
    ll ans = 0;
    rep(a, 4) rep(b, 4) rep(c, 4) {
        ans += dp[N][a][b][c];
        ans %= MOD;
    }
    cout << ans << endl;

    return 0;
}