Description
![](http://www.lydsy.com/JudgeOnline/images/1968.jpg)
Input
只有一行一个整数 N(0 < N < 1000000)。
Output
只有一行输出,为整数M,即f(1)到f(N)的累加和。
Sample Input
3
Sample Output
5
题解
这道题刚开始以为是线性筛
但是有一种更优的算法
考虑因子中有因子i的数的数量
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 //考虑有多少个数是以i为因子的 2 #include<bits/stdc++.h> 3 using namespace std; 4 int n,ans; 5 int main(){ 6 scanf("%d",&n); 7 for (int i=1;i<=n;i++) 8 ans+=n/i; 9 printf("%d\n",ans); 10 return 0; 11 }
这个代码灰常短,也挺好理解的
Solution2:
但是如果想不到怎么办
那就只好强上线性筛了
这里先说一下
num[i]表示i的因子个数,Min[i]表示i的最小质因子的次数
我们可以通过约数个数定理来求一个数的因子个数
传送门:https://baike.so.com/doc/5806281-6019081.html
不难发现一个质数的因子个数为2(1和它本身),最小质因子的次数为1
我们在筛质数的时候判断一下prime[j]是否为i的最小质因子
如果是
num[i*prime[j]]等于num[i]/(Min[i]+1)*(Min[i]+2)
Min[i*prime[j]]等于Min[i]+1 //最小质因子次数+1
如果不是
num[i*prime[j]]就等于num[i]*num[prime[j]] //符合积性函数
Min[i*prime[j]]等于1 //i*prime[j]的最小质因子为prime[j]且只有1次
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 //线性筛 2 #include<bits/stdc++.h> 3 #define N 1000005 4 using namespace std; 5 int n,ans,cnt; 6 int prime[N],num[N],Min[N]; 7 bool flag[N]; 8 int main(){ 9 scanf("%d",&n); 10 num[1]=1; 11 for (int i=2;i<=n;i++){ 12 if (!flag[i]){ 13 prime[++cnt]=i; 14 num[i]=2; 15 Min[i]=1; 16 } 17 for (int j=1;j<=cnt&&i*prime[j]<=n;j++){ 18 flag[i*prime[j]]=true; 19 if (!(i%prime[j])){ 20 num[i*prime[j]]=num[i]/(Min[i]+1)*(Min[i]+2); 21 Min[i*prime[j]]=Min[i]+1; 22 break; 23 } 24 num[i*prime[j]]=num[i]*num[prime[j]]; 25 Min[i*prime[j]]=1; 26 } 27 } 28 for (int i=1;i<=n;i++) 29 ans+=num[i]; 30 printf("%d\n",ans); 31 return 0; 32 }