#pragma GCC target ("avx2")
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>

#define POP pop_back
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define F first
#define S second
#define X real()
#define Y imag()
#define FOR(i,a,b) for (int i = a; i < (int)b; i++)
#define ROF(i,a,b) for (int i = a - 1; i >= (int)b; i--)
#define all(x) (x).begin(), (x).end()
#ifdef LOCAL
    #define debug(...) cerr << "[" << #__VA_ARGS__ << "]:", debug_out(__VA_ARGS__)
#else
    #define debug(...) 0
    #define endl "\n"
#endif

using namespace std;
using namespace chrono;
using namespace __gnu_pbds;

typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vpi;
typedef vector<vi> vvi;
typedef long long ll;
typedef pair<ll, ll> pll;
typedef vector<ll> vll;
typedef vector<pll> vpll;
typedef vector<vll> vvll;
typedef long long C;
typedef complex<C> P;

const int INF = 1e9;
const long long LLINF = 1e18;
const double PI = 3.14159265358979323;
const long long PRIME = (1LL << 31) - 1;
const long long PRIME2 = 269;
const long long MOD = 1e9 + 7; // 998244353;

void debug_out() { cerr << endl; }
template <typename Head, typename... Tail> void debug_out(Head H, Tail... T) { cerr << " " << H; debug_out(T...); }
template <class T1, class T2> istream& operator>>(istream &in, pair<T1, T2> &p) { return in >> p.F >> p.S; }
template <class T1> istream& operator>>(istream &in, vector<T1> &c) { for (auto &x : c) cin >> x; return in; }
template <class T1, class T2> ostream& operator<<(ostream &out, pair<T1, T2> p) { return out << "(" << p.F << ", " << p.S << ")"; }
template <class T1> ostream& operator<<(ostream &out, tuple<T1> t) { return out << "(" << get<0>(t) << ")"; }
template <class T1, class T2> ostream& operator<<(ostream &out, tuple<T1, T2> t) { return out << "(" << get<0>(t) << ", " << get<1>(t) << ")"; }
template <class T1, class T2, class T3> ostream& operator<<(ostream &out, tuple<T1, T2, T3> t) { return out << "(" << get<0>(t) << ", " << get<1>(t) << ", " << get<2>(t) << ")"; }
template <class T1, class T2, class T3, class T4> ostream& operator<<(ostream &out, tuple<T1, T2, T3, T4> t) { return out << "(" << get<0>(t) << ", " << get<1>(t) << ", " << get<2>(t) << ", " << get<3>(t) << ")"; }
template <class T1, class T2> ostream& operator<<(ostream &out, vector<T1, T2> c) { for (auto it = c.begin(); it != c.end(); ++it) { if (it != c.begin()) out << " "; out << *it; } return out; }
template <class T1, class T2, class T3> ostream& operator<<(ostream &out, set<T1, T2, T3> c) { for (auto it = c.begin(); it != c.end(); ++it) { if (it != c.begin()) out << " "; out << *it; } return out; }
template <class T1, class T2, class T3, class T4> ostream& operator<<(ostream &out, map<T1, T2, T3, T4> c) { for (auto it = c.begin(); it != c.end(); ++it) { if (it != c.begin()) out << " "; out << *it; } return out; }
template <class T1, class T2, class T3, class T4> ostream& operator<<(ostream &out, unordered_set<T1, T2, T3, T4> c) { for (auto it = c.begin(); it != c.end(); ++it) { if (it != c.begin()) out << " "; out << *it; } return out; }
template <class T1, class T2, class T3, class T4, class T5> ostream& operator<<(ostream &out, unordered_map<T1, T2, T3, T4, T5> c) { for (auto it = c.begin(); it != c.end(); ++it) { if (it != c.begin()) out << " "; out << *it; } return out; }
template <class T1, class T2> ostream& operator<<(ostream &out, stack<T1, T2> c) { vector<T1> v; for (; !c.empty(); c.pop()) v.PB(c.top()); reverse(v.begin(), v.end()); return out << v; }
template <class T1, class T2> ostream& operator<<(ostream &out, queue<T1, T2> c) { for (; !c.empty(); c.pop()) { out << c.front(); if (c.size() > 1) out << " "; } return out; }
template <class T1, class T2> ostream& operator<<(ostream &out, deque<T1, T2> c) { for (; !c.empty(); c.pop_front()) { out << c.front(); if (c.size() > 1) out << " "; } return out; }
template <class T1> int sign(T1 x) { return (x > 0) - (x < 0); }
template <class T1> T1 sq(T1 x) { return x * x; }
inline ll mod(ll a, ll b) { ll x = a % b; return x >= 0 ? x : x + b; }
inline ll mod(ll a) { return mod(a, MOD); }
C dot(P a, P b) { return a.X * b.X + a.Y * b.Y; }
C cross(P a, P b) { return a.X * b.Y - b.X * a.Y; }
struct custom_hash {
    static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9; x = (x ^ (x >> 27)) * 0x94d049bb133111eb; return x ^ (x >> 31); }
    size_t operator()(uint64_t x) const { static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + FIXED_RANDOM); }
};
ll currTime() { return duration_cast<nanoseconds>(system_clock::now().time_since_epoch()).count(); }
ll startTime = currTime();
ll execTime() { return currTime() - startTime; }
mt19937_64 eng(startTime);
uniform_int_distribution<ll> distr(LLONG_MIN, LLONG_MAX);

template <class T1> using ordered_set = tree<T1, null_type, less<T1>, rb_tree_tag, tree_order_statistics_node_update>;
template <class T1, class T2> using ordered_map = tree<T1, T2, less<T1>, rb_tree_tag, tree_order_statistics_node_update>;
template <class T1> using hash_set = gp_hash_table<T1, null_type, custom_hash>;
template <class T1, class T2> using hash_map = gp_hash_table<T1, T2, custom_hash>;
template <class T1, class T2, class T3, class T4, template <class U1, class U2, class U3, class U4> class T5, class T6> ostream& operator<<(ostream &out, tree<T1, T2, T3, T4, T5, T6> c) { for (auto it = c.begin(); it != c.end(); ++it) { if (it != c.begin()) out << " "; out << *it; } return out; }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, bool T8, class T9> ostream& operator<<(ostream &out, gp_hash_table<T1, T2, T3, T4, T5, T6, T7, T8, T9> c) { for (auto it = c.begin(); it != c.end(); ++it) { if (it != c.begin()) out << " "; out << *it; } return out; }

int main() {
#ifndef LOCAL
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
#endif
    ll n;
    cin >> n;

    const int NONE = 0;
    const int ZERO = 1;
    const int NINE = 2;
    const int BOTH = 3;

    vvll dp(n, vll(4));
    dp[0] = { 8, 1, 1, 0 };
    FOR (i, 1, n) {
        dp[i][NONE] = mod(dp[i - 1][NONE] * 8);
        dp[i][ZERO] = mod(dp[i - 1][NONE] + 9 * dp[i - 1][ZERO]);
        dp[i][NINE] = mod(dp[i - 1][NONE] + 9 * dp[i - 1][NINE]);
        dp[i][BOTH] = mod(dp[i - 1][ZERO] + dp[i - 1][NINE] + 10 * dp[i - 1][BOTH]);
    }
    cout << dp[n - 1][BOTH] << endl;
}

Measured memory_bytes: 73376