题意:求1到n除了本身和1的约数和。
题解:很容易想到O(n)的解法,对于每个数出现的次数为n/i,减去本身,那么求(n/i-1)*i,循环一遍即可。
那么如何优化呢。我们可以先求出前sqrt(n)的数出现的次数,sqrt(n)之后的数出现的次数如何求呢,举个栗子。
n=100,当我们求到7时,7一共出现了100/7次,减去本身出现的一次,ans+=(100/7-1)*7。而100/7>sqrt(100),
100/7=14我们会发现11,12,13,14这些数乘以7都不会大于n,那么我们对这些数求和然后加到ans里面就可以了。
#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <math.h>
using namespace std;
int main()
{
int t;cin>>t;int cas=1;
while(t--)
{
long long ans=0;
long long n,m;
cin>>n;
for(long long i=2;i<=sqrt(n);i++)
{
ans+=(n/i-1)*i;
if(n/i>sqrt(n))
{
long long q=n/i;long long p=sqrt(n)+1;
ans+=(q-p+1)*(q+p)/2;
}
}
printf("Case %d: %lld\n",cas++,ans);
}
return 0;
}