题意:要求对于1~n,每个数的约数(不包括1和其本身)的和。

题解:由于题目数据有2*10^9之大,因而不能直接暴力。需要考虑积性函数的特性,由于必定有重复的约数出现,因而可以对重复约数所在的区间进行合并。由于对于较小的约数,其对应的较大的约数重复区间较小,所以可以先将较小的约数进行合并操作,然后对其对应的较大的约数的区间进行求和。以n=10为例,对于约数2而言,1~10中有2的约数的有10/2-1个(要减去2本身),而对于2在1~10内相对应的约数4和5,则可以直接进行求和操作,求和区间为[sqrt(n)+1,n/i] 。所以我们可以在sqrt(n)的范围内求出所有约数。具体代码如下:

#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
int main()
{
    LL n;
    LL ans,m;
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        LL q,p;
        scanf("%lld",&n);
        ans=0;
        m=(LL)sqrt(n);
        for(LL i=2;i<=m;i++)
        {
            q=n/i;
            ans=ans+(q-1)*i;
            p=m+1;
            if(p>q)
                continue;
            ans=ans+(q-p+1)*(q+p)/2;
        }
        printf("Case %d: %lld\n",cas++,ans);
    }
    return 0;
}

对于积性函数的前缀和的讨论可以参见:

http://blog.csdn.net/skywalkert/article/details/50500009