我们需要分析出本题的几个性质:
首先假设 $\mathrm{[1,N]}$ 中约数个数最多的数的约数个数为 $\mathrm{s}$。
则对于 $\mathrm{[1,N]}$ 中所有的数,满足约数个数为 $\mathrm{s}$ 的所有的数中,反素数是这些数中最小的那个。
反证法:假设存在约数个数为 $\mathrm{s}$ 的两个数 $\mathrm{a, b}$,且 $\mathrm{a > b}$
则 $\mathrm{g(a) \ngtr g(b),但a > b}$,矛盾。因此反素数必定是这些数中最小的那个。
得到上述性质后,继续分析:
-
对于数据范围 $[1, 2 \times 10^9]$,能够满足不同质因子相乘的最大质数为 $28$:
$\mathrm{2 \times 3 \times 5 \times 7 \times 11 \times 13 \times 17 \times 19 \times 23 \times 29 > 6 \times 10^9 \gt 2 \times 10^9}$ -
对于数据范围 $[1, 2 \times 10^9]$,能够满足质因子的最大次数为 $30$:
$2^{31} > 2.1\times10^9 > 2\times10^9$ -
对于数据范围 $[1, 2 \times 10^9]$,质因子从小到大排序,其次数必定是单调递减的:
反证法:假设存在某两个质因子 $a, b ~~ (a > b)$,$a, b$ 的次数分别记为 $k_a,k_b$ ,且 $k_a > k_b$
则对于该反素数 $\mathrm{x = \cdots a^{k_a} \cdot b^{k_b}} \cdots$,必然存在数 $\mathrm{x’ = \cdots a^{k_b} \cdot b^{k_a} \cdots}$ ,满足 $\mathrm{x’ < x}$
而根据我们推导的第一个性质,$\mathrm{x’}$更有可能是所求的反素数,而非$\mathrm{x}$,故矛盾。
根据上述一顿推导,我们最终把该答案锁定在一个很小的区间内了,该区间满足:
1. 质因子次数单调递减
2. 质因子最大枚举到 $28$
3. 单个质因子的次数最多为 $30$
采用上述三个性质,爆搜即可
Code
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
int n;
int s; //s记录当前最大约数个数的数
int maxd; //maxd记录当前最大约数个数的数的约数个数
int primes[9] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
//u是当前枚举到第u个素数, last是前一个素数所枚举的次数
//p就是当前的数, sum是当前数的所有约数个数之和
void dfs(int u, int last, int p, int sum) {
if (sum > maxd || sum == maxd && p < s) {
maxd = sum;
s = p;
}
if (u == 9) return;
for (int i = 1; i <= last; ++ i) {
if ((LL)p * primes[u] > n) return;
p *= primes[u];
dfs(u + 1, i, p, sum * (i + 1));
}
}
int main() {
cin >> n;
dfs(0, 30, 1, 1);
cout << s << endl;
return 0;
}
质因子最大是23吧
对啊,打错了吧
//u是当前枚举到第u个素数, last是前一个素数所枚举的次数
//p就是当前的数, sum是当前数的所有约数个数之和
为什么dfs函数第四个参数在搜索时是i+1?
不是$sum*(i+1)$吗
因为内层每循环一次 约数个数就需要乘以i+1 也就是(指数+1) 因为最开始1次方的那个数也算一个约数