import { readFileSync } from "fs";

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const range = (n: number | bigint) => [...Array(Number(n))].map((_, i) => i);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const tuple = <T extends unknown[]>(...ts: T) => ts;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [cin, nCin, bCin] = (() => {
  const inputs = readFileSync("/dev/stdin", "utf-8").split(/[\n|\s]+/);
  let count = 0;
  const cin = () => inputs[count++];
  return tuple(
    cin,
    () => Number(cin()),
    () => BigInt(cin())
  );
})();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const isNumber = (x: unknown): x is number => typeof x === "number";
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const isBigint = (x: unknown): x is bigint => typeof x === "bigint";
type NumberOrBigintOrElse<T> = number | bigint extends T
  ? undefined
  : T extends number
  ? number
  : T extends bigint
  ? bigint
  : undefined;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const max = <T extends number | bigint>(...ts: T[]) =>
  (ts.length === 0
    ? undefined
    : isNumber(ts[0])
    ? Math.max(...(ts as number[]))
    : (ts as bigint[]).reduce((acc, t) =>
        acc >= t ? acc : t
      )) as NumberOrBigintOrElse<T>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const min = <T extends number | bigint>(...ts: T[]) =>
  (ts.length === 0
    ? undefined
    : isNumber(ts[0])
    ? Math.min(...(ts as number[]))
    : (ts as bigint[]).reduce((acc, t) =>
        acc <= t ? acc : t
      )) as NumberOrBigintOrElse<T>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const abs = <T extends number | bigint>(t: T) =>
  (isNumber(t)
    ? Math.abs(t)
    : isBigint(t)
    ? t >= 0n
      ? t
      : -t
    : undefined) as NumberOrBigintOrElse<T>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const getAddP = <T extends number | bigint>(P: T) =>
  ((x: NumberOrBigintOrElse<T>, y: NumberOrBigintOrElse<T>) =>
    isNumber(x) && isNumber(y) && isNumber(P)
      ? ((((x % P) + (y % P)) % P) + P) % P
      : isBigint(x) && isBigint(y) && isBigint(P)
      ? ((((x % P) + (y % P)) % P) + P) % P
      : (undefined as NumberOrBigintOrElse<T>)) as (
    x: NumberOrBigintOrElse<T>,
    y: NumberOrBigintOrElse<T>
  ) => NumberOrBigintOrElse<T>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const getSubP = <T extends number | bigint>(P: T) =>
  ((x: NumberOrBigintOrElse<T>, y: NumberOrBigintOrElse<T>) =>
    isNumber(x) && isNumber(y) && isNumber(P)
      ? ((((x % P) - (y % P)) % P) + P) % P
      : isBigint(x) && isBigint(y) && isBigint(P)
      ? ((((x % P) - (y % P)) % P) + P) % P
      : (undefined as NumberOrBigintOrElse<T>)) as (
    x: NumberOrBigintOrElse<T>,
    y: NumberOrBigintOrElse<T>
  ) => NumberOrBigintOrElse<T>;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const getProdP = <T extends number | bigint>(P: T) =>
  ((x: NumberOrBigintOrElse<T>, y: NumberOrBigintOrElse<T>) =>
    isNumber(x) && isNumber(y) && isNumber(P)
      ? ((((x % P) * (y % P)) % P) + P) % P
      : isBigint(x) && isBigint(y) && isBigint(P)
      ? ((((x % P) * (y % P)) % P) + P) % P
      : (undefined as NumberOrBigintOrElse<T>)) as (
    x: NumberOrBigintOrElse<T>,
    y: NumberOrBigintOrElse<T>
  ) => NumberOrBigintOrElse<T>;

/**
 * Program
 */
const P = 10n ** 9n + 7n;
const addP = getAddP(P);
const subP = getSubP(P);
const prodP = getProdP(P);
const powP = (x: bigint, n: bigint): bigint => {
  let tmpN = n;
  const isEvens: boolean[] = [];
  while (tmpN !== 1n) {
    isEvens.push(tmpN % 2n === 0n);
    tmpN /= 2n;
  }
  return isEvens.reduceRight((acc, b) => {
    const tmp = prodP(acc, acc);
    return b ? tmp : prodP(x, tmp);
  }, x);
};
const getAns = (N: bigint): string =>
  addP(subP(powP(10n, N), prodP(2n, powP(9n, N))), powP(8n, N)).toString();
{
  const N = bCin();
  const ans = getAns(N);
  console.log(ans);
}


Measured memory_bytes: 29676