#![allow(dead_code)]
#![allow(unused)]
use proconio::input;
#[macro_use]
extern crate lazy_static;

mod modulus {
    pub const MOD: i64 = 1000000007;
    
    use std::sync::RwLock;
    lazy_static! {
        pub(self) static ref NCR_MAXIMUM: RwLock<i32> = RwLock::new(0);
        pub(self) static ref FACTORIAL: RwLock<Vec<i64>> = RwLock::new(Vec::new());
        pub(self) static ref FACTORIAL_INVERSE: RwLock<Vec<i64>> = RwLock::new(Vec::new());
        pub(self) static ref INVERSE: RwLock<Vec<i64>> = RwLock::new(Vec::new());
    }
    
    use std::cmp;
    pub fn prepare_ncr(maximum_value: i32) {
        let mut ncr_maximum = NCR_MAXIMUM.write().unwrap();
        if(maximum_value < *ncr_maximum) { return };
        let maximum_value = cmp::max(2, maximum_value) as usize;
        let mut factorial = FACTORIAL.write().unwrap();
        let mut factorial_inverse = FACTORIAL_INVERSE.write().unwrap();
        let mut inverse = INVERSE.write().unwrap();
        factorial.resize(maximum_value, 0);
        factorial_inverse.resize(maximum_value, 0);
        inverse.resize(maximum_value, 0);
        if(*ncr_maximum <= 2) {
            factorial[0] = 1; factorial[1] = 1;
            factorial_inverse[0] = 1; factorial_inverse[1] = 1;
            inverse[1] = 1;
        }
        for i in cmp::max(2, *ncr_maximum as usize)..maximum_value {
            factorial[i] = factorial[i - 1] * i as i64 % MOD;
            inverse[i] = MOD - inverse[(MOD % i as i64) as usize] * (MOD / i as i64) % MOD;
            factorial_inverse[i] = factorial_inverse[i - 1] * inverse[i] % MOD;
        }
        *ncr_maximum = maximum_value as i32;
    }
    pub fn ncr(n: i32, r: i32) -> ModNumber {
        if(n < r || n < 0 || r < 0)  { return ModNumber::new(0); }
        let ncr_maximum = *NCR_MAXIMUM.read().unwrap();
        if(n >= ncr_maximum || r >= ncr_maximum) { prepare_ncr(cmp::max(n, r) + 1); }
        let factorial = FACTORIAL.read().unwrap();
        let factorial_inverse = FACTORIAL_INVERSE.read().unwrap();
        let inverse = INVERSE.read().unwrap();
        let n = n as usize; let r = r as usize;
        return ModNumber::new(factorial[n] * (factorial_inverse[r] * factorial_inverse[n - r] % MOD) % MOD);
    }
    fn gcd_extended(a: i64, b: i64, x: &mut i64, y: &mut i64) -> i64 {
        if(b == 0) { *x = 1; *y = 0; a }
        else { let d = gcd_extended(b, a % b, y, x); *y -= a / b * *x; d }
    }
    pub fn inverse(a: i64) -> ModNumber {
        let ncr_maximum = *NCR_MAXIMUM.read().unwrap();
        if(a < ncr_maximum as i64) {
            let inverse_ = INVERSE.read().unwrap();
            ModNumber::new(inverse_[a as usize])
        }else{
            let mut x = 0i64;
            let mut y = 0i64;
            gcd_extended(a, MOD, &mut x, &mut y);
            ModNumber::new((MOD + x % MOD) % MOD)
        }
    }
    pub fn pow(a: i32, n: i32) -> ModNumber {
        let mut result = 1i64;
        let mut a = a as i64 % MOD; let mut n = n;
        while n != 0 {
            if(n & 1 != 0) { result = result * a % MOD; }
            a = a * a % MOD; n >>= 1; 
        }
        ModNumber::new(result)
    }

    #[derive(Copy, Clone)]
    pub struct ModNumber {
        pub(self) num: i64
    }

    impl ModNumber {
        pub fn new(n: i64) -> ModNumber {
            ModNumber{num: n % MOD}
        }
        pub fn to_i64(&self) -> i64 {
            self.num
        }
    }

    impl std::ops::Add for ModNumber {
        type Output = Self;
        fn add(self, other: Self) -> Self {
            Self::new(self.num + other.num)
        }
    }
    impl std::ops::AddAssign for ModNumber {
        fn add_assign(&mut self, other: Self) {
            self.num += other.num;
            self.num %= MOD;
        }
    }
    impl std::ops::Sub for ModNumber {
        type Output = Self;
        fn sub(self, other: Self) -> Self {
            Self::new(if self.num < other.num { self.num - other.num + MOD } else { self.num - other.num })
        }
    }
    impl std::ops::SubAssign for ModNumber {
        fn sub_assign(&mut self, other: Self) {
            if self.num < other.num {
                self.num += MOD;
            }
            self.num -= other.num;
            self.num %= MOD;
        }
    }
    impl std::ops::Mul for ModNumber {
        type Output = Self;
        fn mul(self, other: Self) -> Self {
            Self::new(self.num * other.num)
        }
    }
    impl std::ops::MulAssign for ModNumber {
        fn mul_assign(&mut self, other: Self) {
            self.num *= other.num;
            self.num %= MOD;
        }
    }
    impl std::ops::Div for ModNumber {
        type Output = Self;
        fn div(self, other: Self) -> Self {
            self * inverse(other.num)
        }
    }
    impl std::ops::DivAssign for ModNumber {
        fn div_assign(&mut self, other: Self) {
            *self *= inverse(other.num);
            self.num %= MOD;
        }
    }
    impl std::fmt::Display for ModNumber {
        fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
            write!(f, "{}", self.num)
        }
    }

}

fn main() {
    input!(n: i32);
    if(n == 1) {
        println!("{}", 0);
        return;
    }
    let res1 = modulus::pow(10, n);
    let res2 = modulus::pow(9, n);
    let res3 = modulus::pow(8, n);
    println!("{}", res1 - modulus::ModNumber::new(2) * res2 + res3)
}


Measured memory_bytes: 2084