//! # Bundled libraries
//!
//! ## `kyopro_lib` (private)
//!
//! ### Modules
//!
//! - `::__kyopro_lib::modint` → `$crate::modint`

#[allow(unused_imports)]
use itertools::Itertools;
use proconio::input;
#[allow(unused_imports)]
use proconio::marker::*;

/*#[cfg_attr(cargo_equip, cargo_equip::equip)]
use ::__kyopro_lib::modint;*/

type Mint = modint::Mint1_000_000_007;

fn main() {
    input! {
        n: u64,
    }
    let mut res = Mint::new(10).pow(n);
    res -= Mint::new(9).pow(n);
    res -= Mint::new(9).pow(n);
    res += Mint::new(8).pow(n);
    println!("{}", res);
}

// The following code was expanded by `cargo-equip`.

#[allow(clippy::deprecated_cfg_attr)] #[cfg_attr(rustfmt, rustfmt::skip)] pub mod modint { # [doc = " aaa"] pub trait Modulation { const MOD : u64 ; } # [derive (PartialEq)] pub struct ModInt < M : Modulation > { x : u64 , phantom : std :: marker :: PhantomData < M >, } impl < M : Modulation > Clone for ModInt < M > { fn clone (& self) -> Self { Self :: new_uncheck (self . x) } } impl < M : Modulation > Copy for ModInt < M > { } impl < M : Modulation > std :: fmt :: Display for ModInt < M > { fn fmt (& self , dest : & mut std :: fmt :: Formatter <'_ >) -> Result < () , std :: fmt :: Error > { write ! (dest , "{}" , self . x) } } impl < M : Modulation > ModInt < M > { # [inline] pub fn new (x : u64) -> Self { Self { x : x % M :: MOD , phantom : std :: marker :: PhantomData , } } # [inline] pub fn from_signed (x : i64) -> Self { let x = if x >= 0 { x as u64 % M :: MOD } else { (M :: MOD as i64 + x % M :: MOD as i64) as u64 } ; Self { x : x , phantom : std :: marker :: PhantomData , } } # [inline] pub fn new_uncheck (x : u64) -> Self { Self { x : x , phantom : std :: marker :: PhantomData , } } # [inline] pub fn val (& self) -> u64 { self . x } } macro_rules ! def_from_trait { (u , $ t : ty) => { impl < M : Modulation > std :: convert :: From <$ t > for ModInt < M > { # [inline] fn from (x : $ t) -> Self { Self :: new (x as u64) } } } ; (i , $ t : ty) => { impl < M : Modulation > std :: convert :: From <$ t > for ModInt < M > { # [inline] fn from (x : $ t) -> Self { Self :: from_signed (x as i64) } } } ; } def_from_trait ! (u , u8) ; def_from_trait ! (u , u16) ; def_from_trait ! (u , u32) ; def_from_trait ! (u , u64) ; def_from_trait ! (u , usize) ; def_from_trait ! (i , i8) ; def_from_trait ! (i , i16) ; def_from_trait ! (i , i32) ; def_from_trait ! (i , i64) ; def_from_trait ! (i , isize) ; impl < M : Modulation > std :: ops :: Neg for ModInt < M > { type Output = Self ; # [inline] fn neg (self) -> Self { Self { x : if self . x == 0 { 0 } else { M :: MOD - self . x } , phantom : std :: marker :: PhantomData , } } } impl < M : Modulation > std :: ops :: AddAssign for ModInt < M > { # [inline] fn add_assign (& mut self , rhs : Self) { self . x += rhs . x ; if M :: MOD <= self . x { self . x -= M :: MOD ; } } } impl < M : Modulation > std :: ops :: Add for ModInt < M > { type Output = Self ; # [inline] fn add (self , rhs : Self) -> Self { let mut res = self ; res += rhs ; res } } impl < M : Modulation > std :: ops :: SubAssign for ModInt < M > { # [inline] fn sub_assign (& mut self , rhs : Self) { if self . x >= rhs . x { self . x -= rhs . x ; } else { self . x += M :: MOD - rhs . x ; } } } impl < M : Modulation > std :: ops :: Sub for ModInt < M > { type Output = Self ; # [inline] fn sub (self , rhs : Self) -> Self { let mut res = self ; res -= rhs ; res } } impl < M : Modulation > std :: ops :: MulAssign for ModInt < M > { # [inline] fn mul_assign (& mut self , rhs : Self) { self . x *= rhs . x ; self . x %= M :: MOD ; } } impl < M : Modulation > std :: ops :: Mul for ModInt < M > { type Output = Self ; # [inline] fn mul (self , rhs : Self) -> Self { let mut res = self ; res *= rhs ; res } } # [doc = " ax + by = gcd(a,b) を満たす最小のx,yの組 + gcd"] # [doc = " ```"] # [doc = " // assert_eq!(ext_gcd(4,6),(-1,1,2));"] # [doc = " ```"] fn ext_gcd (a : u64 , b : u64) -> (i64 , i64 , u64) { if b == 0 { (1 , 0 , a) } else { let (mut y , x , d) = ext_gcd (b , a % b) ; y -= (a / b) as i64 * x ; (x , y , d) } } impl < M : Modulation > ModInt < M > { pub fn pow (& self , mut n : u64) -> Self { let mut res = Self :: new_uncheck (1) ; let mut d = * self ; while n != 0 { if n & 1 != 0 { res *= d ; } d *= d ; n >>= 1 ; } res } pub fn inv (& self) -> Self { let (mut x , _ , _) = ext_gcd (self . x , M :: MOD) ; if x < 0 { x %= M :: MOD as i64 ; x += M :: MOD as i64 ; } Self :: new (x as u64) } pub fn gen_factorial (n : u64) -> Factorial < M > { let n = n as usize ; let mut pos = vec ! [Self :: new_uncheck (1) ; n + 1] ; let mut neg = vec ! [Self :: new_uncheck (1) ; n + 1] ; for i in 1 .. n { pos [i + 1] = pos [i] * Self :: new (i as u64 + 1) ; } neg [n] = pos [n] . inv () ; for i in (1 .. n) . rev () { neg [i] = neg [i + 1] * Self :: new (i as u64 + 1) ; } Factorial { pos : pos , neg : neg } } pub fn gen_inv (n : u64) -> Vec < Self > { let mut res = vec ! [Self :: new_uncheck (1) ; (n + 1) as usize] ; for i in 2 ..= n { res [i as usize] = Self :: new_uncheck (M :: MOD - M :: MOD / i) * res [(M :: MOD % i) as usize] ; } res } } pub struct Factorial < M : Modulation > { pos : Vec < ModInt < M >>, neg : Vec < ModInt < M >>, } impl < M : Modulation > Factorial < M > { pub fn permutation (& self , n : u64 , r : u64) -> ModInt < M > { if r > n { ModInt :: new (0) } else { self . pos [n as usize] * self . neg [(n - r) as usize] } } pub fn binomial (& self , n : u64 , r : u64) -> ModInt < M > { if r > n { ModInt :: new (0) } else { self . pos [n as usize] * self . neg [r as usize] * self . neg [(n - r) as usize] } } pub fn cmb_with_rep (& self , n : u64 , r : u64) -> ModInt < M > { self . binomial (n + r - 1 , r) } } pub struct F1_000_000_007 ; impl Modulation for F1_000_000_007 { const MOD : u64 = 1_000_000_007 ; } pub type Mint1_000_000_007 = ModInt < F1_000_000_007 >; pub struct F998_244_353 ; impl Modulation for F998_244_353 { const MOD : u64 = 998_244_353 ; } pub type Mint998_244_353 = ModInt < F998_244_353 >; }


Measured memory_bytes: 2152