题面
题目描述
科学家们在 Samuel 星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机 Samuel II 的长时间运算成为了可能。由于在去年一年的辛苦工作取得了不错的成绩,小联被允许用 Samuel II 进行数学研究。
小联最近在研究和约数有关的问题,他统计每个正数 (N) 的约数的个数,并以 (f(N)) 来表示。例如 (12) 的约数有 (1,2,3,4,6,12),因此 (f(12)=6)。下表给出了一些 (f(N)) 的取值:
(N) | (1) | (2) | (3) | (4) | (5) | (6) |
---|---|---|---|---|---|---|
(f(N)) | (1) | (2) | (2) | (3) | (2) | (4) |
现在请你求出:
[sum_{i=1}^n f(i)
]
输入输出格式
输入格式
输入一个整数 (n)。
输出格式
输出答案。
输入输出样例
输入样例 #1
3
输出样例 #1
5
说明
- 对于 (20\%) 的数据,(N leq 5000);
- 对于 (100\%) 的数据,(1 leq N leq 10^6)。
分析
如果纯模拟的话,朴素做法自然是把(n)以内的数全都求一遍因数个数。求一个数的因数个数复杂度为(O(sqrt{i})),那么这种朴素做法是(O(nsqrt{n}))级别的。但我们可以有一种更优秀的做法。
动用我们聪明的大脑,就可以想出,我们还可以枚举(i( 1 le i le n)),求这个因数(i)在(1 sim n)中出现了多少次。那么出现了多少次呢?大可不必在第二层枚举,结果就是(lfloor n/i floor),至于为什么?你想啊,一个因数(i)在(1 sim n)中出现了多少次,其实就是在说(n)以内有多少个(i)的倍数,(i)的倍数每(i)个出现一次,答案自然是(lfloor n/i floor) 。所以我们就有了一种(O(n))的做法:求
[sum_{i=1}^nlfloor n/i
floor
]
代码实现就很简单了,但为了诚意贴个代码:
代码
/*
* @Author: crab-in-the-northeast
* @Date: 2020-02-24 16:52:07
* @Last Modified by: crab-in-the-northeast
* @Last Modified time: 2020-02-24 16:53:12
*/
#include <iostream>
#include <cstdio>
int n;
long long ans;
int main() {
scanf("%d",&n);
for(int i = 1; i <= n; i++) ans += n / i;
printf("%lld
",ans);
return 0;
}
评测结果
AC 100
:R31016131