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)

#[allow(unused_imports)]
use {
    itertools::Itertools,
    proconio::{fastout, input, marker::*},
    std::cmp::*,
    std::collections::*,
    std::io::Write,
    std::ops::*,
};

macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), std::io::stderr());
            writeln!(err, "{} = {:?}", e, $e).unwrap()
        })*
    };
}

macro_rules! mint {
    ($a :expr ) => {
        Mint::new({ $a })
    };
}
const MOD: i64 = 1000000007;
#[derive(Copy, Clone)]
pub struct Mint(i64);
impl Mint {
    fn new(x: i64) -> Self {
        Mint(x.rem_euclid(MOD))
    }
    fn pow(self, n: usize) -> Self {
        match n {
            0 => Mint::new(1),
            _ => {
                let mut a = self.pow(n >> 1);
                a *= a;
                if n & 1 == 1 {
                    a *= self;
                }
                a
            }
        }
    }
    fn inv(self) -> Self {
        self.pow((MOD - 2) as usize)
    }
}
impl std::ops::Neg for Mint {
    type Output = Mint;
    fn neg(self) -> Self::Output {
        Self::new(-self.0)
    }
}
impl std::ops::AddAssign<Mint> for Mint {
    fn add_assign(&mut self, rhs: Self) {
        self.0 += rhs.0;
        self.0 %= MOD;
    }
}
impl std::ops::AddAssign<i64> for Mint {
    fn add_assign(&mut self, rhs: i64) {
        *self += Mint::new(rhs);
    }
}
impl std::ops::AddAssign<usize> for Mint {
    fn add_assign(&mut self, rhs: usize) {
        *self += Mint::new(rhs as i64);
    }
}
impl<T> std::ops::Add<T> for Mint
where
    Mint: std::ops::AddAssign<T>,
{
    type Output = Self;
    fn add(self, other: T) -> Self {
        let mut res = self;
        res += other;
        res
    }
}
impl std::ops::SubAssign<Mint> for Mint {
    fn sub_assign(&mut self, rhs: Self) {
        self.0 -= rhs.0;
        if self.0 < 0 {
            self.0 += MOD;
        }
    }
}
impl std::ops::SubAssign<i64> for Mint {
    fn sub_assign(&mut self, rhs: i64) {
        *self -= Mint::new(rhs);
    }
}
impl std::ops::SubAssign<usize> for Mint {
    fn sub_assign(&mut self, rhs: usize) {
        *self -= Mint::new(rhs as i64);
    }
}
impl<T> std::ops::Sub<T> for Mint
where
    Mint: std::ops::SubAssign<T>,
{
    type Output = Self;
    fn sub(self, other: T) -> Self {
        let mut res = self;
        res -= other;
        res
    }
}
impl std::ops::MulAssign<Mint> for Mint {
    fn mul_assign(&mut self, rhs: Self) {
        self.0 *= rhs.0;
        self.0 %= MOD;
    }
}
impl std::ops::MulAssign<i64> for Mint {
    fn mul_assign(&mut self, rhs: i64) {
        *self *= Mint::new(rhs);
    }
}
impl std::ops::MulAssign<usize> for Mint {
    fn mul_assign(&mut self, rhs: usize) {
        *self *= Mint::new(rhs as i64);
    }
}
impl<T> std::ops::Mul<T> for Mint
where
    Mint: std::ops::MulAssign<T>,
{
    type Output = Self;
    fn mul(self, other: T) -> Self {
        let mut res = self;
        res *= other;
        res
    }
}
impl std::ops::DivAssign<Mint> for Mint {
    fn div_assign(&mut self, rhs: Self) {
        *self *= rhs.inv();
    }
}
impl std::ops::DivAssign<i64> for Mint {
    fn div_assign(&mut self, rhs: i64) {
        *self /= Mint::new(rhs);
    }
}
impl std::ops::DivAssign<usize> for Mint {
    fn div_assign(&mut self, rhs: usize) {
        *self /= Mint::new(rhs as i64);
    }
}
impl<T> std::ops::Div<T> for Mint
where
    Mint: std::ops::DivAssign<T>,
{
    type Output = Self;
    fn div(self, other: T) -> Self {
        let mut res = self;
        res /= other;
        res
    }
}
impl std::fmt::Display for Mint {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}
impl std::ops::Deref for Mint {
    type Target = i64;
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
impl std::ops::DerefMut for Mint {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

#[fastout]
fn main() {
    input! {
        n: usize,
    }

    let mut ans = Mint(0);
    ans += Mint(10).pow(n);
    ans -= Mint(9).pow(n);
    ans -= Mint(9).pow(n);
    ans += Mint(8).pow(n);
    println!("{}", ans);
}