求
∑
i
=
1
n
f
(
i
)
\sum_{i=1}^n f(i)
i=1∑nf(i)
f(i)为因数之和,所以可以转化为
∑
i
=
1
n
∑
d
∣
i
d
\sum_{i=1}^n\sum_{d|i}d
i=1∑nd∣i∑d
因为f(i)不包括i本身,所以最后要减去
n
∗
(
n
+
1
)
2
\frac {n*(n+1)} 2
2n∗(n+1)
我们主要看前面
改变枚举对象为d,转化为
∑
d
=
1
n
d
⌊
n
d
⌋
\sum_{d=1} ^n d\lfloor\frac n d\rfloor
d=1∑nd⌊dn⌋
数论分块即可
因为有一个d,所以比较怪异
令r=n/(n/l)
我们考虑在x∈(l,r)中
⌊
n
x
⌋
\lfloor\frac n x\rfloor
⌊xn⌋为定值都为m,所以每一段为
∑
x
=
l
r
m
x
\sum_{x=l}^r mx
x=l∑rmx
在分块的时候变成
⌊
n
l
⌋
∗
(
l
+
r
)
∗
(
r
−
l
+
1
)
/
2
\lfloor\frac n l \rfloor* (l+r)*(r-l+1)/2
⌊ln⌋∗(l+r)∗(r−l+1)/2就好
代码
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
ll n;
ll f(ll x)
{
ll ans=0;
for(ll l=1,r;l<=x;l=r+1)
{
r=x/(x/l);
ans+=(r-l+1)*(l+r)*(x/l)/2;
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
cout<<(f(n)-((n+1)*n)/2)<<endl;
}
}