[luogu p1403] [AHOI2005]约数研究

传送门

题面

题目描述

科学家们在 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 100R31016131

原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1403.html