P1403 [AHOI2005]约数研究

Posted five20

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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特别大时,优化效果极其鲜明。

代码:

 1 // luogu-judger-enable-o2
 2 #include<bits/stdc++.h>
 3 #define il inline
 4 #define ll long long
 5 using namespace std;
 6 const int N=1000005;
 7 int n,k;
 8 ll ans;
 9 int main()
10 {
11     cin>>n;
12     for(int i=1;i<=n;i=k+1){
13         k=n/(n/i);
14         ans+=n/i*(k-i+1);
15     }
16     cout<<ans;
17     return 0;
18 }

 

以上是关于P1403 [AHOI2005]约数研究的主要内容,如果未能解决你的问题,请参考以下文章

洛谷——P1403 [AHOI2005]约数研究

洛谷 P1403 [AHOI2005]约数研究

P1403 [AHOI2005]约数研究

P1403 [AHOI2005]约数研究

BZOJ 1968: [Ahoi2005]COMMON 约数研究

1968: [Ahoi2005]COMMON 约数研究