反质数

反质数( 数学(star ))

  • 时限:(1s) 内存:(256M)

Descrption

  • 对于任何正整数 (x),其约数的个数记作 (g(x))。例如 (g(1)=1,g(6)=4)
  • 如果某个正整数 (x) 满足:
    • 对任意的 (i(0<i<x)) 满足 (g(x)>g(i)),则称 (x) 为反质数。
    • 例如,整数 (1,2,4,6)等都是反质数。
  • 现在给定一个数 (N) ,你能求出不超过 (N) 的最大的反质数么?

Input

  • 一个数(N(1<=N<=2 imes 10^9))

Output

  • 不超过 (N) 的最大的反质数。

Sample Input

1000

Sample Output

840

Hint

  • 保证 (25\%) 的数据 (1<=N<=10^3).
  • 保证(50\%) 的数据 (1<=N<=1^5).
  • 保证 (75\%) 的数据 (1<=N<=10^8).
  • 保证 (100\%) 的数据 (1<=N<=2 imes 10^9).
  • 来源:(luogup1463)

分析

  • 先举个简单的例子,求一个数 (756) 的约数总个数。

    • 先将 (756) 分解质因子,得到 (756=2^2×3^3×7^1),再把三个指数加一连乘就是 (756) 约数的总个数:((2+1)×(3+1)×(1+1)=24)
  • 在本题中,所要求的是 (1sim N) 范围内最大的反质数,实际上也就是要求约数个数最多的那个数。那么,一个数最多会有多少个不同的质因子呢?最多又会有多少个约数呢?

    • 粗略估算:(2×3×5×7×11×13×17×19×23×29=6469693230>2×10^9)。所以,我们就得到了一个很重要的性质:
      • 性质一:在 (1sim 2×10^9) 中,一个数最多有 (10) 个不同的质因子。
      • 性质二:在 (1sim 2×10^9) 中一个数其约数个数大致也就是 (10^4sim 10^5) 级别。
    • 这两个性质虽然是通过估算得出的,但其正确性是无庸质疑的。在以后的算法设计中,这两个性质将起着举足轻重的作用。
  • 再回头看对正整数 (756) 的分析:(756=2^2×3^3×7^1) ,共有 (24) 个约数。那么它是否是一个“反质数”呢? 显然,我们可以构造出另一个正整数,也有 (24) 个约数,却比 (756) 要小:(540=2^2×3^3×5^1)

    • 构造反例的原理在于,(756) 的质因子 (2,3,7) 不是连续的质数,漏了 (5),用 (5) 代替 (7),而指数不变就可以构造出一个更小的但有着相同约数个数的正整数。因此,我们又得到了一个关于“反质数”的性质:
      • 性质三:一个反质数的质因子必然是从 (2) 开始连续的质数。
    • 分析至此,对“一个数和其约数”,“反质数”我们已有了初步的了解,并且大致掌握了一些基础性质。下面,在这些分析的基础上,我们开始尝试着设计一个时间效率上能够被接受的算法。
  • 算法设计

    • 由于题目中 (N) 的范围很大——有 (2×10^9),所以想通过求出每个数约数的个数,最后通过统计找出最大的反质数,这种方法效率很低,是不现实的。我们必须另辟蹊径。
    • (1sim 2×10^9) 中有很多数显然不是“反质数”,在先前的分析中,性质三就充分说明了这一点。
    • 根据题目对“反质数”的定义,我们知道,不可能有两个反质数,其约数个数相同。那么,根据性质二,“反质数”的个数将远远小于 (2×10^9),而只是 (10^4)(10^5) 级别。这样一来,我们就可以考虑直接产生所有的“反质数”,再从中找出最大的。
    • 在先前的题意分析中,我们知道:“反质数”与一个数的约数总数,质因子总数都有着莫大的联系,不妨将这个因素放在一起。
    • (f[i][j]) 记录的是:约数总数为 (i),有 (j) 个不同的质因子的最小正整数。
    • 还是举个简单例子,(f[12][3]=60,60=2^2×3^1×5^1)。而 (f[6][2]=12=2^2×3^1) ,即:(f[12][3]=f[6][2]×5)
    • 状态转移方程:假设 (p[j]) 记录的是第 (j) 大的质数。
      • $ f[i][j]=min(f[frac{i}{k+1}][j-1]*p[j]^k)$ 其中 (i mod (k+1)==0,p[j]^k<=N)
    • 边界条件:$ f[1][0]=1$ 。
    • 以质因子个数 (j) 为阶段。根据性质二,参数 (i) 的范围不超过是(10^5),参数 (j) 的范围不超过 (10)。所以,算法的空间复杂度还是可以承受的,不超过 (O(sqrt(N)log2N))。在状态转移中,由于有 (p[j]^2<=N),所以 (k) 不会超过 (log2N),因此,算法的时间复杂度不超过 (O(sqrt(N)(log2N)^2)) 也是可以被接受的。
  • 方法二:

    • 由于(2*3*5*7*11*13*17*19*23*29>2*10^9) ,所以可以通过搜索枚举约数
    • 如果反素数 (n=p_1^{a_1}*p_2^{a_2}*...*p_n^{a_n}),它的约束个数为 ((a_1+1)*(a_2+1)*...*(a_n+1)) ,而且我们很容易知道 (a_1>=a_2>=a_3>=...>=a_n) 。所以通过搜索枚举各素约数的个数很快就能过了。。。。。
原文地址:https://www.cnblogs.com/hbhszxyb/p/13402992.html