• P1403 [AHOI2005]约数研究


    题目描述

    科学家们在Samuel星球上的探险得到了丰富的能源储备,这使得空间站中大型计算机“Samuel II”的长时间运算成为了可能。由于在去年一年的辛苦工作取得了不错的成绩,小联被允许用“Samuel II”进行数学研究。

    小联最近在研究和约数有关的问题,他统计每个正数N的约数的个数,并以f(N)来表示。例如12的约数有1、2、3、4、6、12。因此f(12)=6。下表给出了一些f(N)的取值:

    f(n)表示n的约数个数,现在给出n,要求求出f(1)到f(n)的总和。

    输入输出格式

    输入格式:

    输入一行,一个整数n

    输出格式:

    输出一个整数,表示总和

    输入输出样例

    输入样例#1: 
    3
    
    输出样例#1: 
    5
    

    说明

    【数据范围】

    20%N<=5000

    100%N<=1000000

    Solution:

    本题纯考数学,因为需要求1到n的数所含的各自的约数和,我们可以转换为:1~n中是1的倍数的数有n/1个,是2的倍数的有n/2个,是3的倍数的数有n/3个,…直到n/n,于是直接O(n)扫一遍每次ans+=n/i就ok了。

    当然上述的方法可以完美解决本题,但有一种适用于更大数据的巧妙优化方法,思路和上面是一样的,但是我们考虑到当i枚举到比较大时,会出现重复的n/i,举个例子:

    当n为100时,n/i(1≤i≤100)分别为:
    100 50 33 25 20 16 14 12 11 10 9 8 7 7 6 6 5 5 5 5 4 4 4 4 4 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    容易发现出现了许多重复的数,而我们完全没必要重复去算而是直接一次性累加完。

    方法是设x=n/i,y=n/x,x表示的是n内i的倍数的个数,y表示n内因子个数为x的最大因子(即i最多枚举到y,每次n/i的值都为x),则显然因子个数为x的i值共y-i+1个,于是ans+=x*(y-i+1),然后i直接变为y+1;

    这样去优化的话:复杂度从O(n)变为了O(2*sqrt(n)),在n特别大时,优化效果极其鲜明。

    代码:

    #include<bits/stdc++.h>
    #define il inline
    #define ll long long
    using namespace std;
    const int N=1000005;
    int n,k;
    ll ans;
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i=k+1){
            k=n/(n/i);
            ans+=n/i*(k-i+1);
        }
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    XMLHttpRequest对象垃圾回收
    Stored XSS攻击
    重写setTimeout
    js instanceof Object Function
    maven的环境搭建
    Struts2整合json
    分页框架(Pager-taglib)的使用及sitemesh的简单使用
    首页文章标题分页
    在线HTML编辑器的引入
    Sparse PCA: reproduction of the synthetic example
  • 原文地址:https://www.cnblogs.com/five20/p/8573078.html
Copyright © 2020-2023  润新知