LOJ 1089
题意 :
The function SOD(n) (sum of divisors) is defined as the summation of all the actual divisors of an integer number n. For example, SOD(24) = 2+3+4+6+8+12 = 35.

给出一个n,让求csod(n), n的范围在2*10^9;
思路: 这道题主要的思想是枚举除数, 很显然在n的范围内除数可以出现的值在2~~n。
每个除数i,出现的次数为(n/i-1), 其值为(n/i-1)*i; 我们可以算 sum(n/i*i),最后再把多余的项给补出来。
如果一个一个枚举的话肯定会tle的。 然后就是如何降低复杂度,其实对于每道题,看到数据之后应该想着正解算法的复杂度大概是多少,复杂度是这样的算法有哪些?然后就是如何才能降低这个复杂度呢?
其实给出了这个n的范围我们应该往√n 的复杂度上想。首先√n以前的数可以枚举,√n后的数n/i的值是在一些区间中的。并且这些区间中的值是连续的。 我们可以利用这个性质,并且只有√n 个区间。 n/i == k 的区间是[n/(k+1)+1, n/k];
这道题RE一次。 主要是0的时候出现了一次。 数论题可能会有一些有特例(一般是小数据)。
AC代码:
View Code
1 #include <cstdio> 2 #include <string> 3 #include <queue> 4 #include <cstring> 5 #include <cmath> 6 #include <iostream> 7 using namespace std; 8 typedef unsigned long long ULL; 9 10 ULL n; 11 12 int main() 13 { 14 int t; 15 n = 2; 16 scanf("%d", &t); 17 ULL ans, ss, l, r, k; 18 for(int i=1; i<=t; i++) 19 { 20 scanf("%llu", &n); 21 printf("Case %d: ", i); 22 if(n <= 3) 23 { 24 puts("0"); 25 continue; 26 } 27 ans = 0; 28 ss = (ULL)sqrt(n*1.0); 29 for(int i=2; i<=ss; i++) 30 { 31 ans += n/i*i; 32 } 33 l = ss+1; 34 k = n/l; 35 r = n/k; 36 ans += k*(r+l)*(r-l+1)/2; 37 for(ULL j=k-1; j>=1; --j) 38 { 39 l = n/(j+1) +1; 40 r = n/j; 41 ans += j*(r+l)*(r-l+1)/2; 42 } 43 44 ans -= (2+n)*(n-2+1)/2; 45 printf("%llu\n", ans); 46 } 47 return 0; 48 }


浙公网安备 33010602011771号