#include <bits/stdc++.h>
using namespace std;
//=====================================================
// マクロ定義部
//=====================================================

#define FOR(i,a,b) for(ll i = (a); i < (b); ++i)
#define FOR_EQ(i,a,b) for(ll i = (a); i <= (b); ++i)
#define rep(i,n) FOR(i,0,n)
#define rep_eq(i,n) FOR_EQ(i,0,n)
#define DEBUG_VARIABLE(variable) cout << #variable << ":" << variable << endl
#define INFTY 1000000000000
#define WHITE 1//（未訪問）
#define GRAY 2//（訪問）未だに訪問していない頂点への辺を持っている。スタックに退避。
#define BLACK 3//（訪問完了）未訪問への頂点への辺を持たない
//=====================================================
// 型定義部
//=====================================================

typedef unsigned long long ull;
typedef long long ll;
typedef pair<ll, ll>    ll_ll;
typedef vector<ll> Vector;
typedef vector<Vector> DVector;
typedef vector< pair<ll, ll> > Vec_Pair;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0 ;}
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0 ;}
//===================================================
// 関数のプロトタイプ宣言・関数に必要な配列の宣言
//===================================================

template <class X> void printArray(X *array, ll);
template <class X> void printVector(vector<X> &v);
template <class X> void printDimention(vector< vector<X> > &dv);
template <class X> void printMap(X);
template <class X> void printVecPair(vector<X> &v);
void printDV_Pair(vector<vector<pair<ll, ll> > > &v);
void printSet(set<ll> &S);
// 繰返し自乗法
ll RepeatSquaring(ll a, ll index);
// 最大公約数
ll GCD(ll, ll);
// 最小公倍数
ll LCM(ll, ll);
// 割り算した時に余りが有る時だけ、+1の商を返す。
ll div_one(ll res, ll div);

//===================================================
// グローバル
//===================================================

const int MOD = 1000000007;
//1個上から時計周り
const int ddx[8] = {0, 1, 1, 1, 0, -1, -1, -1};
const int ddy[8] = {1, 1, 0, -1, -1, -1, 0, 1};
//上右下左
const int dx[4] = {0, 1, 0, -1};    // dj
const int dy[4] = {-1, 0, 1, 0};    // di
static const int NIL = -1;

ll N, k, K, V, E;

//===================================================
// 関数
//===================================================
/**
 * 二項係数( nCk = n!/(k! * (n - k)!) )用の各階乗の値とその逆元を記録するための配列．
 * fac: 分子、inv: 分母(逆元１つ)、finv: 逆元の累積値
 * オーバーフローなどで負の数になってしまうと、MOD 演算で狂いが生じるので、
 * unsigned にしてしまう
 */
const int TABLEMAX = 1000001;
unsigned long long fac[TABLEMAX], inv[TABLEMAX], finv[TABLEMAX];

/**
 * 使用方法
 * 逆元を使って二項係数（組み合わせ）を求める
 * nCr の n が510000以下
 *     COMinit() -> COM(n, r)
 * nCr の n が510000より大きい。メモリ容量が足りない場合、繰返し自乗法を用いて求める(combination_MOD関数)
 *     combination_MOD
 * 制限なし
 *     combination
 *     factrial
 */

/**
 * main関数内で COMinit を呼んだ後、COM を呼ぶ．
 * MOD 界における話。COM の返り値も MOD の余が返ってくる。
 * fac: 分子の累積、inv: 分母(逆元１つ)、finv: 逆元の累積値
 * fac と finv は順列だと思いましょう
 * MOD界においては a^-1 = a^(MOD - 2)
 */
// テーブルを作る前処理
void COMinit() {
    fac[0] = fac[1] = 1;
    finv[0] = finv[1] = 1;
    inv[1] = 1;
    // i は数を表す
    // fac[5] = 5!
    // inv[5] = 5 の MOD における逆元
    // finv[5]
    for (int i = 2; i < TABLEMAX; i++){
        fac[i] = (fac[i - 1] * i) % MOD;
        // 拡張ユークリッドで高速に計算
        inv[i] = MOD -  inv[MOD % i] * (MOD / i)  % MOD;
        finv[i] = (finv[i - 1] * inv[i]) % MOD;
    }
}
// 二項係数計算 nCk, nCrのcombinationでも使える
long long COM(ll n, ll k){
    if (n < k) return 0;
    if (n < 0 || k < 0) return 0;
    // finv[n - k] で 分子のいらない部分を相殺
    return fac[n] * (finv[k] * finv[n - k] % MOD) % MOD;
}

/**
 * MODを使用した繰返し自乗法
 * a: 基数, index: 指数, M: MOD
 */
ll RepeatSquaring_MOD(ll a, ll index, ll M){
    // Nは基数、Pは指数、MはMOD
    if(index == 0)  return 1;
    if(index % 2 == 0){
        ll tmp = RepeatSquaring_MOD(a, index/2, M);
        return tmp * tmp % M;
    }else{
        return a * RepeatSquaring_MOD(a, index - 1, M) % M;
    }
}

/**
 * 二項係数の計算
 * COMinit では数の範囲が大幅に超えてしまう時に使用
 * r が TLE 以下ならば、使用できる
 */
ll combination_MOD(ll n, ll r){
    ll nume = 1, denom = 1;
    FOR_EQ(i, n - r + 1, n){
        nume = (nume * i) % MOD;
    }
    FOR_EQ(i, 1, r){
        denom = (denom * i) % MOD;
    }
    denom = RepeatSquaring_MOD(denom, MOD - 2, MOD);

    return (nume * denom) % MOD;
}

//nCr
ll combination(ll n, ll r){
    if(n == 0 || r == 0 || n < r)    return 0;
    ll up = 1, down = 1;
    // 以下2行はお試し
    ll half = n / 2;
    if(r >= half)   r = n - r;
    ll up_tmp = n, down_tmp = r;

    if(r == 0)  return 1;
    rep(i, r){
        up *= up_tmp;
        up_tmp--;
        down *= down_tmp;
        down_tmp--;
    }

    return up/down;
}

//nPr
int factorial(int n, int r){
    if(n < r){
        cout << "error" << endl;
        return 0;
    }else{
        int res = 1;
        while(r){
            r--;
            res *= n;
            n--;
        }
        return res;
    }
}

//===================================================
// main 問題処理部
//===================================================
int main(int argc, char const *argv[])
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> N;
    if(N == 1){
        cout << 0 << endl;
        return 0;
    }
    COMinit();
    ll sum = 0;
    FOR_EQ(k, 2, N){
        ll two = RepeatSquaring_MOD(2, k, MOD) - 2;
        if(two < 0) two += MOD;

        ll eight = RepeatSquaring_MOD(8, N - k, MOD);

        //ll comb = combination_MOD(N, k);
        ll comb = COM(N, k);

        ll tmp = (two * eight) % MOD;
        tmp = (tmp * comb) % MOD;
        sum += tmp;
        sum %= MOD;
    }
    cout << sum << endl;

    return 0;
}

//=====================================================
// 関数群
//=====================================================

template<class X> void printArray(X array[], ll n){
    rep(i, n){
        if(i)   cout << " ";
        cout << array[i];
    }
    cout << endl;
}

template<class X> void printVector(vector<X> &v){
    rep(i, (int)v.size()){
        if(i)   cout << " ";
        cout << v[i];
    }
    cout << endl;
}

//二次元配列の表示
template<class X> void printDimention(vector< vector<X> > &dv){
    rep(i, (ll)dv.size()){
        rep(j, (ll)dv[i].size()){
            if(j)   cout << " ";
            cout << dv[i][j];
        }
        cout << endl;
    }
    cout << endl;
}

//mapの表示
template <class X> void printMap(X mp) {
    for (auto it : mp) {
        cout << it.first << " " << it.second << endl;
    }
}

// 内部にpairを内包したvectorの表示
template <class X> void printVecPair(vector<X> &v){
    rep(i, (int)v.size()){
        cout << v[i].first << " " << v[i].second << endl;
    }
    cout << endl;
}

// 内部にVec_Pairを内包したvectorの表示
void printDV_Pair(vector<vector<pair<ll, ll> > > &v){
    rep(i, (int)v.size()){
        cout << i << endl;
        rep(j, (int)v[i].size()){
            cout << v[i][j].first << " " << v[i][j].second << endl;
        }
        cout << endl;
    }
    cout << endl;
}

void printSet(set<ll> &S){
    for(set<ll>::iterator it = S.begin(); it != S.end(); it++){
        if(it != --S.end() ) cout << *it << " ";
        else    cout << *it << endl;
    }
}

ll RepeatSquaring(ll a, ll index){
    if(index == 0)  return  1;
    else if(index % 2 == 0){
        ll tmp = RepeatSquaring(a, index / 2);
        return tmp * tmp;
    }else{
        return a * RepeatSquaring(a, index - 1);
    }
}

//最大公約数(Greatest Common Divisor)
// ユークリッドの互除法使用
ll GCD (ll a, ll b){
    return b ?  GCD(b, a % b) : a;
}

//最小公倍数(Least Common Multiple)
ll LCM(ll m, ll n){
    //引数に0がある場合は0を返す
    if(m == 0 || n == 0)    return 0;

    //lcm = m * n / gcd(m, n)
    return ((m / GCD(m, n)) * n);
}

// 割り算した時に余りが有る時だけ、+1の商を返す。
ll div_one(ll res, ll div){
    // res 割られる数、div 割る数
    return (res + div - 1)/div;
}

Measured memory_bytes: 27068