Problem:
Score : 300 points

Problem Statement

How many integer sequences A_1,A_2,\ldots,A_N of length N satisfy all of the following conditions?

0 \leq A_i \leq 9

There exists some i such that A_i=0 holds.

There exists some i such that A_i=9 holds.

The answer can be very large, so output it modulo 10^9 + 7.

Constraints

1 \leq N \leq 10^6

N is an integer.

Input

Input is given from Standard Input in the following format:

N

Output

Print the answer modulo 10^9 + 7.

Sample Input 1

2

Sample Output 1

2

Two sequences \{0,9\} and \{9,0\} satisfy all conditions.

Sample Input 2

1

Sample Output 2

0

Sample Input 3

869121

Sample Output 3

2511445

Solution in Rust (1.42.0) (judge verdict: Accepted)

// template {{{
#![allow(clippy::many_single_char_names)]

#[allow(dead_code)]
mod ngtio {
    use ::std::collections::VecDeque;

    pub struct Buffer {
        buf: VecDeque<String>,
    }

    impl Buffer {
        pub fn new() -> Self {
            Self {
                buf: VecDeque::new(),
            }
        }

        fn load(&mut self) {
            while self.buf.is_empty() {
                let mut s = String::new();
                let length = ::std::io::stdin().read_line(&mut s).unwrap();
                if length == 0 {
                    break;
                }
                self.buf.extend(s.split_whitespace().map(|s| s.to_owned()));
            }
        }

        pub fn string(&mut self) -> String {
            self.load();
            self.buf
                .pop_front()
                .unwrap_or_else(|| panic!("入力が終了したのですが。"))
        }

        pub fn string_char_vec(&mut self) -> Vec<char> {
            let s = self.string();
            s.chars().collect::<Vec<_>>()
        }

        pub fn string_char_vec_trusted_len(&mut self, len: usize) -> Vec<char> {
            let s = self.string();
            let s = s.chars().collect::<Vec<_>>();
            assert_eq!(s.len(), len, "あら、思ったのと長さ違いますね……");
            s
        }

        pub fn char(&mut self) -> char {
            let string = self.string();
            let mut chars = string.chars();
            let res = chars.next().unwrap();
            assert!(
                chars.next().is_none(),
                "char で受け取りたいのも山々なのですが、さては 2 文字以上ありますね？"
            );
            res
        }

        pub fn read<T: ::std::str::FromStr>(&mut self) -> T
        where
            <T as ::std::str::FromStr>::Err: ::std::fmt::Debug,
        {
            self.string()
                .parse::<T>()
                .expect("Failed to parse the input.")
        }

        pub fn read_vec<T: ::std::str::FromStr>(&mut self, len: usize) -> Vec<T>
        where
            <T as ::std::str::FromStr>::Err: ::std::fmt::Debug,
        {
            (0..len).map(|_| self.read::<T>()).collect()
        }
    }

    macro_rules! define_primitive_reader {
        ($($ty:tt,)*) => {
            impl Buffer {
                $(
#[inline]
                    pub fn $ty(&mut self) -> $ty {
                        self.read::<$ty>()
                    }
                )*
            }
        }
    }

    define_primitive_reader! {
        u8, u16, u32, u64, usize,
        i8, i16, i32, i64, isize,
    }

    impl Default for Buffer {
        fn default() -> Self {
            Self::new()
        }
    }
}

#[allow(unused_imports)]
use std::{collections, iter, mem, ops};
// }}}
// fp {{{
#[allow(dead_code)]
mod fp {
    use crate::constant::Constant;
    use std::{cmp, fmt, iter, mem, ops::*};

    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
    pub struct Fp<Mod: Constant>(Mod::Output);

    impl<Mod: Constant> Fp<Mod>
    where
        Mod::Output: Value,
    {
        #[inline]
        pub fn new(src: Mod::Output) -> Self {
            Self(Self::normalize(src))
        }

        #[inline]
        pub fn from_frac(num: Mod::Output, den: Mod::Output) -> Self {
            Self::new(num) / Self::new(den)
        }

        #[inline]
        pub fn into_inner(self) -> Mod::Output {
            self.0
        }

        #[inline]
        pub fn zero() -> Self {
            Self(Mod::Output::zero())
        }

        #[inline]
        pub fn one() -> Self {
            Self(Mod::Output::one())
        }

        #[allow(clippy::many_single_char_names)]
        pub fn inv(self) -> Self {
            assert_ne!(
                self.into_inner(),
                Mod::Output::zero(),
                "さては 0 の逆元を取ろうとしていますね？"
            );
            let mut x = self.into_inner();
            let mut y = Mod::VALUE;
            let mut u = Mod::Output::one();
            let mut v = Mod::Output::zero();
            while x != Mod::Output::zero() {
                let q = y / x;
                y -= q * x;
                v -= q * u;
                mem::swap(&mut x, &mut y);
                mem::swap(&mut u, &mut v);
            }
            assert!(
                x == Mod::Output::zero()
                    && y == Mod::Output::one()
                    && (u == Mod::VALUE || u == -Mod::VALUE)
                    && (-Mod::VALUE < v && v < Mod::VALUE)
            );
            Self(Self::normalize_from_the_top(v))
        }

        pub fn pow(mut self, mut p: u64) -> Self {
            let mut ans = Self::one();
            while p != 0 {
                if p % 2 == 1 {
                    ans *= self;
                }
                self *= self;
                p /= 2;
            }
            ans
        }

        #[inline]
        fn normalize(src: Mod::Output) -> Mod::Output {
            Self::normalize_from_the_top(src % Mod::VALUE)
        }

        #[inline]
        fn normalize_from_the_bottom(src: Mod::Output) -> Mod::Output {
            if Mod::VALUE <= src {
                src - Mod::VALUE
            } else {
                src
            }
        }

        #[inline]
        fn normalize_from_the_top(src: Mod::Output) -> Mod::Output {
            if src < Mod::Output::zero() {
                src + Mod::VALUE
            } else {
                src
            }
        }
    }

    impl<Mod: Constant> Add for Fp<Mod>
    where
        Mod::Output: Value,
    {
        type Output = Self;

        #[inline]
        fn add(self, rhs: Self) -> Self {
            Self(Self::normalize_from_the_bottom(
                self.into_inner() + rhs.into_inner(),
            ))
        }
    }

    impl<Mod: Constant> Sub for Fp<Mod>
    where
        Mod::Output: Value,
    {
        type Output = Self;

        #[inline]
        fn sub(self, rhs: Self) -> Self {
            Self(Self::normalize_from_the_top(
                self.into_inner() - rhs.into_inner(),
            ))
        }
    }

    impl<Mod: Constant> Mul for Fp<Mod>
    where
        Mod::Output: Value,
    {
        type Output = Self;

        #[inline]
        fn mul(self, rhs: Self) -> Self {
            Self::new(self.into_inner() * rhs.into_inner())
        }
    }

    #[allow(clippy::suspicious_arithmetic_impl)]
    impl<Mod: Constant> Div for Fp<Mod>
    where
        Mod::Output: Value,
    {
        type Output = Self;

        #[inline]
        fn div(self, rhs: Self) -> Self {
            self * rhs.inv()
        }
    }

    impl<Mod: Constant> Neg for Fp<Mod>
    where
        Mod::Output: Value,
    {
        type Output = Self;

        #[inline]
        fn neg(self) -> Self {
            if self.into_inner() == Mod::Output::zero() {
                Self::zero()
            } else {
                Self(Mod::VALUE - self.into_inner())
            }
        }
    }

    impl<Mod: Constant> Neg for &Fp<Mod>
    where
        Mod::Output: Value,
    {
        type Output = Fp<Mod>;

        #[inline]
        fn neg(self) -> Fp<Mod> {
            if self.into_inner() == Mod::Output::zero() {
                Fp::zero()
            } else {
                Fp(Mod::VALUE - self.into_inner())
            }
        }
    }

    impl<Mod: Constant> iter::Sum<Fp<Mod>> for Fp<Mod>
    where
        Mod::Output: Value,
    {
        fn sum<I>(iter: I) -> Self
        where
            I: iter::Iterator<Item = Fp<Mod>>,
        {
            iter.fold(Self::zero(), Add::add)
        }
    }

    impl<'a, Mod: 'a + Constant> iter::Sum<&'a Fp<Mod>> for Fp<Mod>
    where
        Mod::Output: Value,
    {
        fn sum<I>(iter: I) -> Self
        where
            I: iter::Iterator<Item = &'a Fp<Mod>>,
        {
            iter.fold(Self::zero(), Add::add)
        }
    }

    impl<Mod: Constant> iter::Product<Fp<Mod>> for Fp<Mod>
    where
        Mod::Output: Value,
    {
        fn product<I>(iter: I) -> Self
        where
            I: iter::Iterator<Item = Fp<Mod>>,
        {
            iter.fold(Self::one(), Mul::mul)
        }
    }

    impl<'a, Mod: 'a + Constant> iter::Product<&'a Fp<Mod>> for Fp<Mod>
    where
        Mod::Output: Value,
    {
        fn product<I>(iter: I) -> Self
        where
            I: iter::Iterator<Item = &'a Fp<Mod>>,
        {
            iter.fold(Self::one(), Mul::mul)
        }
    }

    macro_rules! forward_assign_biop {
        ($(impl $trait:ident, $fn_assign:ident, $fn:ident)*) => {
            $(
                impl<Mod: Constant> $trait for Fp<Mod>
                where
                    Mod::Output: Value
                {
                    #[inline]
                    fn $fn_assign(&mut self, rhs: Self) {
                        *self = self.$fn(rhs);
                    }
                }
            )*
        };
    }
    forward_assign_biop! {
        impl AddAssign, add_assign, add
        impl SubAssign, sub_assign, sub
        impl MulAssign, mul_assign, mul
        impl DivAssign, div_assign, div
    }

    macro_rules! forward_ref_binop {
        ($(impl $imp:ident, $method:ident)*) => {
            $(
                impl<'a, Mod: Constant> $imp<Fp<Mod>> for &'a Fp<Mod>
                where
                    Mod::Output:Value
                {
                    type Output = Fp<Mod>;

                    #[inline]
                    fn $method(self, other: Fp<Mod>) -> Self::Output {
                        $imp::$method(*self, other)
                    }
                }

                impl<'a, Mod: Constant> $imp<&'a Fp<Mod>> for Fp<Mod>
                where
                    Mod::Output:Value
                {
                    type Output = Fp<Mod>;

                    #[inline]
                    fn $method(self, other: &Fp<Mod>) -> Self::Output {
                        $imp::$method(self, *other)
                    }
                }

                impl<'a, Mod: Constant> $imp<&'a Fp<Mod>> for &'a Fp<Mod>
                where
                    Mod::Output:Value
                {
                    type Output = Fp<Mod>;

                    #[inline]
                    fn $method(self, other: &Fp<Mod>) -> Self::Output {
                        $imp::$method(*self, *other)
                    }
                }
            )*
        };
    }
    forward_ref_binop! {
        impl Add, add
        impl Sub, sub
        impl Mul, mul
        impl Div, div
    }

    impl<Mod: Constant> fmt::Display for Fp<Mod>
    where
        Mod::Output: Value,
    {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
            write!(f, "{}", self.0)
        }
    }

    pub trait Value:
        Sized
        + Clone
        + Copy
        + fmt::Debug
        + fmt::Display
        + cmp::PartialOrd
        + cmp::PartialEq
        + cmp::Ord
        + cmp::Eq
        + Add<Output = Self>
        + Sub<Output = Self>
        + Mul<Output = Self>
        + Div<Output = Self>
        + Rem<Output = Self>
        + Neg<Output = Self>
        + AddAssign
        + SubAssign
        + MulAssign
        + DivAssign
        + RemAssign
    {
        fn zero() -> Self;
        fn one() -> Self;
    }

    macro_rules! impl_value {
        ($($type:ty,)*) => {
            $(
            impl Value for $type {
                #[inline]
                fn zero() -> $type {
                    0
                }
                #[inline]
                fn one() -> $type {
                    1
                }
            }
            )*
        };
    }

    impl_value! {
        i8, i16, i32, i64, i128, isize,
    }
}
// }}}
// constant {{{
#[allow(dead_code)]
mod constant {
    #[macro_export]
    macro_rules! define_constant {
        (type $wrapper_type:ident: $value_type:ty = $value:expr;) => {
            #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
            struct $wrapper_type {}

            impl constant::Constant for $wrapper_type {
                type Output = $value_type;
                const VALUE: Self::Output = $value;
            }
        };
    }

    pub trait Constant: Copy {
        type Output: Copy;
        const VALUE: Self::Output;
    }
}
// }}}

define_constant! { type Mod: i64 = 1_000_000_007; }
type Fp = fp::Fp<Mod>;

fn main() {
    let mut buf = ngtio::Buffer::new();
    let n = buf.u64();
    let ans = Fp::new(10).pow(n) - Fp::new(9).pow(n) - Fp::new(9).pow(n) + Fp::new(8).pow(n);
    println!("{}", ans);
}