BZOJ 1968 [Ahoi2005]COMMON 约数研究

1968: [Ahoi2005]COMMON 约数研究

Description

Input

只有一行一个整数 N(0 < N < 1000000)。

Output

只有一行输出,为整数M,即f(1)到f(N)的累加和。

Sample Input

3

Sample Output

5

  这一定是一道水题,当时因为这是练习积性函数的“好机会”,结果发现自己实在想得太复杂。0 < N < 1000000,因数不会超过这个界限,那么跑一遍就完了。代码也不用挂了。(52ms

  但我发现,也可以欧拉筛。(288 ms

  当然,还可使用区间乱跳,O(1)算出n div i为一定值的区间,而这种区间是O(sqrt(n))的。(0 ms

 

 1 /************************************************************** 
 2     Problem: 1968 
 3     User: Doggu 
 4     Language: C++ 
 5     Result: Accepted 
 6     Time:288 ms 
 7     Memory:13516 kb 
 8 ****************************************************************/
 9   
10 #include <cstdio> 
11 const int SIZE= 1000000; 
12 int prime[SIZE], pri, n; 
13 bool vis[SIZE+10]; 
14 long long  ans, tao[SIZE+10]; 
15 void EULER(int upper_bound) { 
16     tao[1]=1; 
17     for( long long i = 2; i <= upper_bound; i++ ) { 
18         if(!vis[i]) { 
19             prime[++pri]=i; 
20             tao[i]=2; 
21         } 
22         for( int t = 1; t <= pri; t++ ) { 
23             long long j = i*prime[t]; 
24             if(j>upper_bound) break; 
25             vis[j]=1; 
26             tao[j]=tao[i]*tao[prime[t]]; 
27             if(i%prime[t]==0) { 
28                 long long a = i,tot=0; 
29                 while(a%prime[t]==0) a/=prime[t],tot++; 
30                 tao[j]=tao[a]*(tot+2); 
31                 break; 
32             } 
33         } 
34     } 
35 } 
36 int main() { 
37     scanf("%d",&n); 
38     EULER(n+10); 
39     for( int i = 1; i <= n; i++ ) ans+=tao[i]; 
40     printf("%lld\n",ans); 
41     return 0; 
42 }
EULER

 

 

 

 

 

 

 

 

 

 

 

 
posted @ 2017-06-05 12:16  Doggu  阅读(185)  评论(0编辑  收藏  举报