UVALive 7340 Sum of MSLCM

来源:互联网 发布:大数据在医疗领域应用 编辑:程序博客网 时间:2024/06/05 22:40

题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5362


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




0 0