前置知识
试除法求约数 和试除法求质数是类似的道理
约数必须在整除的前提下才存在,而因数是从乘积的角度来提出的.如果数a与数b相乘的积是数c,a与b都是c的因数。
约数只能对在==正整数==范围内而言,因为0
不能整除任何数而因数就不限于整数的范围。
对于一个整数,凡能整除它的数,都是这个整数的约数。约数和因数一样 都可以成对出现
输入一个数 要求从小到大不重复输出每个约数
|
|
复杂度分析
1 ,2 ,3 ···n
2是所有倍数的约数 其他同理 , 则求倍数的个数和求约数的个数一样
1~n当中倍数的个数和约数的个数是一样的
1 + n/2+3/n+···n/n
loglog n 但外层是根号n 总体根号n
欧拉筛约数个数
约数个数定理
根据惟一分解定理 $$n=p_1^{\alpha_1} p_2{ }^{\alpha_2} \cdots p_s^{\alpha_s}, (p_1<p_2<\cdots<p_s)$$
则$$d(n)=\prod_{i=1}^{n}(a_{i}+1)$$
证明:
根据整数唯一分解性定理,每一个质数次方 $ p_{1}^{a_i}$ 的约数有$ p_{i}^{0}$ , $p_{1}^{1}$,···$p_{1}^{a_i}$ 共(a~i~+1)个 选法
根据组合原理和乘法定理 , 则$ d(n)=\prod_{i=1}^{n}(a_{i}+1) $ 每个质因子幂次数+1的连乘积
那么我们使用a[]
数组来保存最小质因子的次数$a_{0},a_{1}…a_{i} $
而 d[]
自然是保存约数个数
显然 d[]
需要借助a[]
来递推
如果为质数
最小质因子初始化为1
(本身) , 约数个数初始化为 2
(1 和 本身) (1+$a_{i}$)
|
|
接下来在处理合数的过程中
m = i * pj
分为 两种情况 如果 pj
为m
的最小质因子 和 pj
不是m
的最小质因子
若i % pj == 0
$pj$ 一定是$i$ 的最小质因数 , 也一定是$m$的最小质因数
$m = i \times pj$ 若存在更小的质因数 在之前早就已经被筛选掉
因为在这里 $pj$ 又贡献了一个最小质因子次数 更新 $a[m]$
|
|
那 $d[m]$如何求
由$d(n) = (1+a_{1})\times(1+a_{2})\times\cdots\times(1+a_{n})$
那么$d(i) = (1+a_{1})\times(1+a_{2})\times\cdots\times(1+a_{i})$
= $ (1+a[i])\times(1+a_{2})\times\cdots\times(1+a_{i})$
而$m$ 比 $i$的基础上再多一个最小质因子$pj$ ($i\times pj = m$)
既
$d(m) = (1+1+a_{1})\times(1+a_{2})\times\cdots\times(1+a_{i})$
=$(a[m] + 1) \times(1+a_{2})\times\cdots\times(1+a_{i}) $
借助d[i]
= $(a[m] + 1) \times \frac{d(i)}{(1+a[i])}$
|
|
若i
不能被pj整除 则 i 不包含质因子pj
|
|
则初始化a[m] = 1 ; 因为i 不包含质因子pj ,此时得到了一个pj(从小到大枚举的) 所以这个1
的贡献就是来自pj , m = i * pj, 既pj必然为m的最小质因子 贡献1
$d(i) = (1+a_{1})\times(1+a_{2})\times\cdots\times(1+a_{i})\times 1$
又∵$pj$ 为最新贡献 且不属于 $i$的因数($i%pj!=0$) 由 乘法原理
$d[m] = (1+a_{1})\times(1+a_{2})\times\cdots\times(1+a_{i})\times (1+1)$
|
|
筛选1…n的约数个数
|
|
法2
算出n的所有质因子 及约数个数
一个合数n中最多只包含一个大于根号n的质因子
最多 包括 没有这种情况
证明 :反证 如果有两个大于sqrt(n)的因子,那么相乘会大于n
|
|
参考