• [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

  • 相关阅读:
    C++ STL list
    1159 Palindrome
    3070 Fibonacci
    1458 Common Subsequence
    git工具之重写历史
    git工具之修订版本(revision)选择
    git工具之使用git调试
    程序员也要听歌啊 写写歌词~(毛不易)《借》《消愁》《像我这样的人》
    git基本命令讲解
    git工作原理
  • 原文地址:https://www.cnblogs.com/crab-in-the-northeast/p/luogu-p1403.html
Copyright © 2020-2023  润新知