Problem:
Score : 900 points

Problem Statement

For a positive integer n, let us define f(n) as the number of digits in base 10.

You are given an integer S.
Count the number of the pairs of positive integers (l, r) (l \leq r) such that f(l) + f(l + 1) + ... + f(r) = S, and find the count modulo 10^9 + 7.

Constraints

1 \leq S \leq 10^8

Input

Input is given from Standard Input in the following format:

S

Output

Print the answer.

Sample Input 1

1

Sample Output 1

9

There are nine pairs (l, r) that satisfies the condition: (1, 1), (2, 2), ..., (9, 9).

Sample Input 2

2

Sample Output 2

98

There are 98 pairs (l, r) that satisfies the condition, such as (1, 2) and (33, 33).

Sample Input 3

123

Sample Output 3

460191684

Sample Input 4

36018

Sample Output 4

966522825

Sample Input 5

1000

Sample Output 5

184984484

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

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);
}