#![allow(unused_imports)]
#![allow(clippy::many_single_char_names)]

// language: Rust(1.42.0)
// check available crates on AtCoder at "https://atcoder.jp/contests/language-test-202001"
// My Library Repo' is at "https://github.com/Loptall/prcn_lib"

/*
    6月で水色になるぞ〜!!!
*/

// from std...
use std::cmp::{
    max, min,
    Ordering::{Equal, Greater, Less},
    Reverse,
};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::mem::swap;
use std::ops::*;
use std::process::exit;
use std::{f32, f64, i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize};

// Dep' crates are...
use itertools::*;
use itertools_num::*;
use lazy_static::lazy_static;
use maplit::{btreemap, btreeset, hashmap, hashset};
use num_bigint::{BigInt, BigUint};
use num_complex::Complex;
use num_integer::{binomial, gcd, lcm, Integer};
use num_rational::Rational;
use num_traits::{clamp, one, pow, zero, One, Pow, Zero};
use permutohedron::Heap;
use petgraph::unionfind::UnionFind;
use proconio::{fastout, input, is_stdin_empty, marker::*};
use rand::random;

pub const MOD: usize = 1000000007;
pub const MAX: usize = 1usize << 63usize;
pub const MIN: i64 = i64::MIN;
pub const PI: f64 = f64::consts::PI;
pub const A: u8 = 'A' as u8;

/// 初期化の際にだけエラストテネスの篩を使って素数のリストを生成
///
/// `O(n)`
pub struct Sieve {
    size: usize,
    /// `(0..=n)`までの範囲で
    /// `is_prime[i]` => `i`は素数
    is_prime: Vec<bool>,
    /// `(0..=n)`の全ての素数
    primes: Vec<usize>,
}
impl Sieve {
    /// 初期化、サイズが重要
    pub fn new(n: usize) -> Self {
        let mut spf = vec![None; n + 1];
        let mut is_prime = vec![true; n + 1];
        let mut primes = Vec::new();
        is_prime[0] = false;
        is_prime[1] = false;
        for i in 2..n + 1 {
            if is_prime[i] {
                primes.push(i);
                spf[i] = Some(i);
            }
            for prime in &primes {
                if i * prime >= n + 1 || prime > &spf[i].unwrap() {
                    break;
                }
                is_prime[i * prime] = false;
                spf[i * prime] = Some(*prime);
            }
        }
        Self {
            size: n,
            is_prime,
            primes,
        }
    }
    /// 自分自身の素数リストの有効な範囲
    pub fn size(&self) -> usize {
        self.size
    }
    /// `n`以下の全ての素数のリストを作る
    pub fn primes(&self, n: usize) -> Vec<usize> {
        assert!(self.size() >= n);
        self.primes
            .iter()
            .take_while(|x| **x <= n)
            .cloned()
            .collect()
    }
    /// `n`が素数かどうか
    ///
    /// # Panic
    /// `n > self.size`でindexing panicする
    pub fn is_prime(&self, n: usize) -> bool {
        self.is_prime[n]
    }
}
/// Seiveテーブルを用いた素因数分解
///
/// `n`を素因数分解するためには最小で、
/// `√n`までのサイズの素数テーブルが必要
///
/// # Panic
/// `sieve`のサイズが`√n`未満で不十分な場合にpanicします
pub fn factorizations_with_sieve(sieve: &Sieve, mut n: usize) -> Vec<(usize, usize)> {
    assert!(sieve.size.pow(2) >= n);
    let mut res = Vec::new();
    let ps = sieve.primes((n as f64).sqrt().ceil() as usize);
    for p in ps {
        let mut c = 0usize;
        while n % p == 0 {
            n /= p;
            c += 1;
        }
        if c != 0 {
            res.push((p, c));
        }
    }
    if n > 1 {
        res.push((n, 1));
    }
    res
}

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

    let sieve = Sieve::new(n);

    let mut d = vec![0usize; n + 1];

    for k in 1..=n {
        (1..).map(|x| x * k).take_while(|x| *x <= n).for_each(|x| {
            d[x] += 1;
        })
    }

    let ans = d
        .into_iter()
        .enumerate()
        .map(|x| {
            // dbg!(x);
            x.1 * x.0
        })
        .sum::<usize>();
    println!("{}", ans);
}


Measured memory_bytes: 173332