约数相关知识点详解

约数相关知识点详解

本篇随笔讲解信息学奥林匹克竞赛中数学部分的约数相关知识点。大体包括:整数唯一分解定理的推论(N)的正约数集合筛选(1 - N)每个数的正约数集合。需要读者有不低于高中一年级的数学素养及一定的逻辑推理能力。本篇随笔将不再对一些基本定理和数学知识、概念进行讲解,有需要的同学请自行补习。

  • 整数唯一分解定理的推论

通过质数相关知识点的学习,我们知道了一个正整数可以被分解成若干质数的乘积,数学表示为:

[N=prod_{i=1}^{i=m}{p_i}^{c_i} ]

将其展开,可以得到:

[N=1 imes p_1 imes p_1^2 imescdots imes p_1^{c_1} imes cdots imes p_m^{c_m-1} imes p_m^{c_m} ]

通过约数的定义,我们可知这个展开式中的所有元素都是(N)的约数。

那么,根据乘法原理,(N)的约数个数(T)就可以表示为:

[T=(1+c_1) imes(1+c_2) imescdots imes(1+c_m) ]

即:

[T=prod_{i=1}^{i=m}(1+c_i) ]

这就是正整数的正约数个数表达式

那么,还是根据正整数的唯一分解定理,(N)的所有正约数的和(S)就是:

[S=(1+p_1+cdots+p_1^{c_1}) imescdots imes(1+p_m+p_m^{c_m}) ]

即:

[S=prod_{i=1}^{i=m}{(sum_{j=0}^{j=c_i}{p_i}^{j})} ]

这就是正整数的所有约数和表达式

  • (N)的正约数集合

我们知道了一个正整数的约数和和约数个数,但是我们还是不能知道这个正整数的约数到底是什么。想要知道具体的约数,需要枚举实现。

但是约数有一个性质:它是成对出现的(完全平方数除外)。

假如一个正整数(a)(N)的约数,且(alesqrt n),那么必然会有一个正整数(b)(N)的约数,且(bgesqrt n)

而且根据约数的性质,我们完全可以断定,这个(b)就是(frac{N}{a})

因此,和质数的判定对应地,我们使用试除法。同样只需要枚举(1 - sqrt N)的所有数,每枚举到一个可被(N)整除的数,就把这个数和(N)除这个数所得的数一起加入到约数集合中。

当然,在细节实现上要判一下它是不是完全平方数。

代码:

void factor(int n)
{
	for(int i=1;i<=sqrt(n);i++)
		if(n%i==0)
		{
			f[++cnt]=i;
			if(i!=n/i)
				f[++cnt]=n/i;
		}
}

并且,通过试除法的原理,我们还可以推导出:

一个数的约数个数的上界为(2sqrt N)

  • 筛选(1-N)每个数的正约数集合

如果用上述方法进行求解,时间复杂度为(O(Nsqrt N)),会被卡。根据约数的定义,我们可以推出:对于每个数(d),这个(1 -N)的数列中以之为约数的数一定是它的倍数。即(d,2d,3d,4dcdotslfloor N/d floor imes d)

所以,我们每枚举到一个数的时候,就直接把它的上述倍数加进表格即可。

代码:

vector<int> f[maxn];
void factors(int n)
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n/i;j++)
            f[i*j].push_back(i);
}

上述算法的时间复杂度是(O(NlogN))级别的。

原文地址:https://www.cnblogs.com/fusiwei/p/11439191.html