这是个比较简单的整除分块吧..

但是我不是数论选手,所以就先去写D了..

这个题还是比较裸的,如果知道约数和的写法的话

首先考虑直接求约数和不太现实,所以我们可以枚举约数,求约数对答案的贡献。

首先1~n所有的约数最大值不可能超过n

所以我们可以考虑所有的约数,用f(i)表示i的倍数在n之前有多少个,那么有公式:

所以自然有下面的求和公式:

该和可以以的复杂度求和,所谓整除分块,具体证明不提(网上一搜一片),如果你和我一样对于数学不敏感,那么就直接记住:

而且取值最多有 种,所以复杂度稳定在根号下

剩下的就套一下就好了,注意计算时涉及到等差数列求和:

/*** keep hungry and calm CoolGuang!  ***/
//#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const ll maxn = 1e6+700;
const int M = 1e6+8;
const ll mod= 1e6+7;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
ll get(ll x){
    ll ans = 0;
    for(int i=1;i<=x;i++){
        int r = (x/(x/i));
        ans += (r-i+1ll)*(x/i)*(x+i)/2;
        i = r;
    }
    return ans;
}
int main(){
    read(n);
    printf("%lld\n",get(get(n)));
    return 0;
}