[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(n\sqrt{n})\)级别的。但我们可以有一种更优秀的做法。

动用我们聪明的大脑,就可以想出,我们还可以枚举\(i( 1 \le i \le n)\),求这个因数\(i\)\(1 \sim n\)中出现了多少次。那么出现了多少次呢?大可不必在第二层枚举,结果就是\(\lfloor n/i \rfloor\),至于为什么?你想啊,一个因数\(i\)\(1 \sim n\)中出现了多少次,其实就是在说\(n\)以内有多少个\(i\)的倍数,\(i\)的倍数每\(i\)个出现一次,答案自然是\(\lfloor n/i \rfloor\) 。所以我们就有了一种\(O(n)\)的做法:求

\[\sum_{i=1}^n\lfloor n/i \rfloor \]

代码实现就很简单了,但为了诚意贴个代码:

代码

/*
 * @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\n",ans);
    return 0;
}

评测结果

AC 100R31016131

posted @ 2020-02-26 01:09  dbxxx  阅读(181)  评论(0编辑  收藏  举报