题意:求2~n每个数的因子和的和。
思路:我们可以发现i加了n/i次。而且次数的个数很少,比如加1次的就有(n+1)/2个。所以我们就枚举次数,二分上下界。每次将同次数的数求和累加答案。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define rep(i,j,k) for (int i=j;i<=k;i++)
#define Rrep(i,j,k) for (int i=j;i>=k;i--)
#define Clean(x,y) memset(x,y,sizeof(x))
#define LL long long
int n;
int main()
{
while( scanf("%d",&n) == 1 )
{
if ( !n ) break;
LL ans = n-1; //1出现了n-1次
LL st = n-(n+1)/2+1;
ans += (LL)(n+1)/2*( st + n )/2; //单独计算次数为1的答案即后(n+1)/2个数求和
int t = n/2;
int L = 2 , R = n;//当前上下界
int m;
while( t!= 1 ) //如果次数为1,那么已经全部统计完了
{
int l = L;
int r = R;
while( l < r ) //二分当前次数的上下界
{
m = ( l + r ) >> 1;
if ( n / (m+1) >= t )
l = m + 1;
else r = m;
}
ans += (LL)t * (r-L+1)*(L+r)/2; //次数 * (范围内数的和)
L = l + 1; //更新边界和下一个次数
t = n / L;
}
printf("%lld\n",ans);
}
return 0;
}