fn getline() -> String {
    let mut res = String::new();
    std::io::stdin().read_line(&mut res).ok();
    res
}

#[allow(unused_macros)]
macro_rules! readl {
    ($t: ty) => {
        {
            let s = getline();
            s.trim().parse::<$t>().unwrap()
        }
    };
    ($( $t: ty),+ ) => {
        {
            let s = getline();
            let mut iter = s.trim().split(' ');
            ($(iter.next().unwrap().parse::<$t>().unwrap(),)*)
        }
    };
}

#[allow(unused_macros)]
macro_rules! readlvec {
    ($t: ty) => {
        {
            let s = getline();
            let iter = s.trim().split(' ');
            iter.map(|x| x.parse().unwrap()).collect::<Vec<$t>>()
        }
    }
}

#[allow(unused_macros)]
macro_rules! debug {
    ($x: expr) => {
        println!("{}: {:?}", stringify!($x), $x)
    }
}
// macro_rules! debug {
//     ($x: expr) => {}
// }

fn printiter<'a, T>(v: &'a T)
where
    &'a T: std::iter::IntoIterator,
    <&'a T as std::iter::IntoIterator>::Item: std::fmt::Display,
{
    for (i, e) in v.into_iter().enumerate() {
        if i != 0 {
            print!(" ");
        }
        print!("{}", e);
    }
    println!("");
}

fn gcd(x: i64, y: i64) -> i64 {
    if y == 0 {
        x
    } else {
        gcd(y, x % y)
    }
}

fn extgcd(a: i64, b: i64) -> (i64, i64) {
    if b == 1 {
        (0, 1)
    } else {
        let (x, y) = extgcd(b, a % b);
        (y, x - a / b * y)
    }
}

macro_rules! make_modint {
    ($MOD: expr, $name: ident) => {
        #[derive(Ord, Hash, Eq, PartialOrd, PartialEq)]
        struct $name {
            val: i64,
        }

        impl $name {
            fn new(x: i64) -> $name {
                let x = x%$MOD;
                $name{val: if x < 0 { x+$MOD } else { x }}
            }

            fn pow(&self, x: i64) -> $name {
                let mut res = $name::new(1);
                let mut tmp = x;
                let mut p = *self;
                while tmp != 0 {
                    if tmp&1 == 1 {
                        res *= p;
                    }
                    tmp = tmp>>1;
                    p = p*p;
                }
                res
            }

            fn inv(&self) -> $name {
                assert!(self.val != 0);
                let mut a = self.val;
                let mut b = $MOD;
                let mut u = 1;
                let mut v = 0;
                use std::mem::swap;
                while b != 0 {
                    let t = a/b;
                    a -= t*b;
                    swap(&mut a, &mut b);
                    u -= t*v;
                    swap(&mut u, &mut v);
                }
                $name::new(u)
            }
        }

        impl std::clone::Clone for $name {
            fn clone(&self) -> $name {
                $name{ val: self.val }
            }
        }

        impl std::marker::Copy for $name { }

        impl std::ops::Add for $name {
            type Output = $name;
            fn add(self, y: $name) -> $name {
                let tmp = self.val+y.val;
                $name{val: if tmp >= $MOD {tmp-$MOD} else {tmp}}
            }
        }

        impl std::ops::Neg for $name {
            type Output = $name;
            fn neg(self) -> $name {
                $name::new(self.val)
            }
        }

        impl std::ops::Sub for $name {
            type Output = $name;
            fn sub(self, other: $name) -> $name{
                let tmp = self.val-other.val;
                $name{val: if tmp < 0 {tmp+$MOD} else {tmp}}
            }
        }

        impl std::ops::Mul for $name {
            type Output = $name;
            fn mul(self, y: $name) -> $name {
                $name{val: (self.val*y.val)%$MOD}
            }
        }

        impl std::ops::Div for $name {
            type Output = $name;
            fn div(self, other: $name) -> $name {
                self*other.inv()
            }
        }

        impl std::fmt::Display for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}", self.val)
            }
        }

        impl std::ops::AddAssign for $name {
        fn add_assign(&mut self, other: $name) {
            *self = *self+other;
        }
        }

        impl std::ops::SubAssign for $name {
            fn sub_assign(&mut self, other: $name) {
                *self = *self-other;
            }
        }

        impl std::ops::MulAssign for $name {
            fn mul_assign(&mut self, other: $name) {
                *self = *self*other;
            }
        }

        impl std::ops::DivAssign for $name {
            fn div_assign(&mut self, other: $name) {
                *self = *self*other.inv();
            }
        }

        impl std::fmt::Debug for $name {
            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
                write!(f, "{}", self.val)
            }
        }
    }
}

make_modint!(1_000_000_000 + 7, ModInt);

fn mint(x: i64) -> ModInt {
    ModInt::new(x)
}

fn div_ceil(x: i64, y: i64) -> i64 {
    let xt = x.abs();
    let yt = y.abs();
    if (x < 0) ^ (y < 0) {
        -(xt / yt)
    } else {
        (xt + yt - 1) / yt
    }
}

fn div_floor(x: i64, y: i64) -> i64 {
    let xt = x.abs();
    let yt = y.abs();
    if (x < 0) ^ (y < 0) {
        -((xt + yt - 1) / yt)
    } else {
        xt / yt
    }
}

fn cnt(s: i64, n: i64) -> i64 {
    let mut res = 0;
    // let count_digit = |mut x| {
    //     let mut res = 0;
    //     while x != 0 {
    //         res += 1;
    //         x /= 10;
    //     }
    //     res
    // };

    let mut p = 1;
    let mut ne = 10;
    let mut dn = 1;
    let mut pdn = 1;
    let mut pne = 10;
    let mut sum = 0;
    for i in 1..n+1 {
        if i == ne {
            dn += 1;
            ne *= 10;
        }
        if p < i {
            sum = 0;
            p = i;
        }
        while sum < s {
            sum += pdn;
            p += 1;
            if p == pne {
                pdn += 1;
                pne *= 10;
            }
        }
        if sum == s {
            res += 1;
        }
        sum -= dn;
    }
    res
}


#[allow(unused_imports)]
use std::cmp::{max, min};
#[allow(unused_imports)]
use std::collections::{BTreeMap, BinaryHeap, HashMap, HashSet};
#[allow(unused_imports)]
use std::collections::btree_map::Entry::{Occupied, Vacant};

fn main() {
    use std::io::Write;
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    macro_rules! printf { ($($arg:tt)*) => (write!(out, $($arg)*).unwrap()); }
    macro_rules! printfln { () => (writeln!(out).unwrap()); ($($arg:tt)*) => (writeln!(out, $($arg)*).unwrap()); }

    let s = readl!(i64);
    let bo = 8;
    let mut ans = mint(cnt(s, 10i64.pow(bo as u32-1)-1));
    // debug!(ans);
    let m = (s+1)/bo;
    for k in 1..1_000_000_00 {
        let a = s/k;
        let b = s%k;
        if a >= bo && b <= k {
            // debug!((k, a, b));
            if b == 0 {
                ans += mint(9) * mint(10).pow(a - 1) - mint(k);
            }
            ans += mint(1);
        }
    }
    printfln!("{}", ans);

    // debug!(div_ceil(-4, -3));

    // let dn = 15;
    // for l in 1..dn + 1 {
    //     let mut sum = 0;
    //     for r in l + 1..dn + 1 {
    //         if sum >= s {
    //             break;
    //         }
    //         debug!(sum);
    //         let v = s - sum;
    //         // if v % g != 0 {
    //         //     continue;
    //         // }
    //         // let g = gcd(l, r);
    //         // let vv = v / g;
    //         // let ll = l / g;
    //         // let rr = r / g;
    //         // let (aa, bb) = extgcd(ll, rr);
    //         // let aa = aa * vv;
    //         // let bb = bb * vv;
    //         // let lt = max(
    //         //     div_ceil(-aa, rr) + 1,
    //         //     div_ceil(bb - 9 * 10i64.pow(r as u32 - 1), ll),
    //         // );
    //         // let rt = min(
    //         //     div_floor(9 * 10i64.pow(l as u32 - 1) - aa, rr),
    //         //     div_floor(bb, ll) - 1,
    //         // );

    //         // ans += mint(max(0, rt - lt + 1));
    //         ans += mint(naive_count(l, r, v));
    //         debug!((l, r));
    //         // debug!((lt, rt));
    //         // debug!(mint(max(0, rt - lt + 1)));
    //         debug!(naive_count(l, r, v));
    //         // assert_eq!(naive_count(l, r, v), hoge(l, r, v));
    //         // assert_eq!(naive_count(l, r, v), max(0, rt - lt + 1));
    //         sum += 9 * 10i64.pow(r as u32 - 1);
    //     }
    // }
    // debug!(ans);
    // for x in (1..).filter(|&x| s%x == 0).take_while(|&x| x * x <= s) {
    //     let f = |x, y| {
    //         if x > 15 {
    //             mint(9) * mint(10).pow(x - 1) - mint(y)
    //         } else {
    //             if y > 9 * 10i64.pow(x as u32 - 1) {
    //                 mint(0)
    //             } else {
    //                 mint(9) * mint(10).pow(x - 1) - mint(y)
    //             }
    //         }
    //     };
    //     let y = s / x;
    //     ans += if x != y { f(x, y) + f(y, x) } else { f(x, y) };
    // }
    // printfln!("{}", ans);
}


Measured memory_bytes: 4352