题目: Dertouzos
看完题目,很容易想到在区间 [1,n) 内遍历,数出最大真因子为 d 的数有多少个,明显超时.
反过来想,如果一个正整数 t 的最大真因子是 d ,那么一定有
t=x⋅d,x≤d枚举这个 x ,数出 x⋅d<n 的有多少个就行了.
虽然把遍历区间换到了 d 上,但还是会超时.
对 x 进行分析,假设 x 是合数,那么有
x=p1a1⋅p2a2…pnan此时
t=p1x⋅(d⋅p1)d⋅p1>d与 d 为 t 的最大真因子矛盾,所以 x 是素数.
遍历序列长度减少,大约是 lndd.
当 d 是素数时,按上述方式遍历素数序列.
当 d 是合数时
d=p1a1⋅p2a2…pnan考虑 x 在 p 序列中的位置,若 x > p1,则
tt=p1a1⋅x⋅p2a2⋅⋯⋅pnan=p1⋅(p1a1−1)⋅x⋅p2a2⋅⋯⋅pnanp1t>d所以 d 不是 t 的最大真因子,构造错误.
所以 x≤p1.
因此需要遍历的素数到 d 的最小质因子为止.
整理一下,我们需要遍历素数序列 P ,使用 Pi 和 d 乘出一个正整数 t ,如果 t<n,它就符合要求,遍历到 d 的最小质因子 p1 为止.
答案就是这个有序集合的基数
∣{Pi⋅d∣Pi⋅d<n,Pi≤p1,i=1,2,…}∣用线性素数筛预先计算出足够的素数,对每组数据分别求答案即可.
本题数据范围 109.
若 d>109,则当 x 接近 109 时, x⋅d>n 一定成立.
若 d<109,则 d 的最小质因子一定小于 109.
因此需要计算的最大素数只要大于 109 即可,大约 32000.
代码:dertouzos.cpp