題意:求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;
}