LightOJ

题意:定义SOD(n)=n除去1和自身的所有因数的和,CSOD(n)为ΣSOD(i),1<=i<=n。T (≤ 1000)组数据,求CSOD(n),(0 ≤ n ≤ 2 * 109)

对于不同的数m,m=a*b,a<=b;枚举a,判断不大于n的中有哪些可以写成m=a*b的,把a和b加到答案上。复杂度是O(√n)

如何维护答案呢?

举例子,作为a出现的3有多少次呢?是n/3 * 3吗?并不是。要注意到我们要求a<=b,那么从m=9开始,3才会作为a出现,而3,6中的因数3并不作为a对答案贡献。所以ans += (n / i - i + 1) * i;

a为一个数时,对应的b成等差数列,最大值是n / i,最小值是a+1,(注意m=a*a时,a只能算一次贡献, 所以这里不是a)

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <cmath>
 5 #define INF 0x3f3f3f3f
 6 using namespace std;
 7 typedef long long LL;
 8 
 9 int T;
10 LL N;
11 
12 int main() {
13     scanf("%d", &T);
14     for (int t = 1; t <= T; t++) {
15         LL ans = 0;
16         scanf("%lld", &N);
17         LL tmp = sqrt(N);
18         for (LL i = 2; i <= tmp; i++) {
19             ans += (N / i - i + 1) * i;
20             LL down = i + 1, up = N / i;
21             //if (down > up) continue; 因为down > up的情况只会出现于n可表示为n=x *x 的情况,此时down = up + 1。下方右式恰好为0
22             ans += (up + down) * (up - down + 1) / 2;
23         }
24         printf("Case %d: %lld
", t, ans);
25     }    
26     return 0;
27 }
原文地址:https://www.cnblogs.com/xFANx/p/7529281.html