分解质因数 约数个数 DFS T3 P1463 [POI2001][HAOI2007] 反素数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题目描述
对于任何正整数 ,其约数的个数记作 。例如 ,。
如果某个正整数 满足:,都有 ,则称 为反质数。例如,整数 等都是反质数。
现在给定一个数 ,你能求出不超过 的最大的反质数么?
输入格式
一个数 。
输出格式
不超过 的最大的反质数。
样例 #1
样例输入 #1
1000
样例输出 #1
840
提示
思路
一个数是反素数的条件是在 中不存在 , 即 x 的约数个数是最大的。
而又因为 x 要是最大的, 因此结果就是 1到n 中约数个数最大的数。
对于 2e9 这个范围, 其不同的质因数也是很有限的, 可以尝试 看看什么时候超 2e9, 实践后发现仅仅乘到 29 就已经是 6e9 了, 故最多只会乘到 23, 也就是用到 9 种质因子。
即第一个性质:不同的质因子最多会有9种
第二个性质:每个质因子的次数最大也是30, 即 。
我们只关心约数个数, 因此分解质因数后的底数是什么无所谓, 只需要确保指数正确就行。
因此第三个性质:所有质因子的次数一定递减。假如存在质因子分解 , 对于结果来说与 是一样的。
至此, 一个显而易见的方法就浮出水面了, 直接DFS爆搜。
搜索每个质因子的次数即可。DFS函数中传入 当前搜到第几个质数, 上一个的次数, 当前值, 以及约数个数。
代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e6 + 10;
int n, res, number;
int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
void dfs(int u, int last, int now, int ans)
{
if (ans > res || ans == res && now < number)
{
res = ans;
number = now;
}
if (u == 9)
return;
for (int i = 1; i <= last; i++)
{
if ((LL)primes[u] * now > n)
break;
now = primes[u] * now;
dfs(u + 1, i, now, ans * (i + 1));
}
}
void solve()
{
cin >> n;
dfs(0, 30, 1, 1);
cout << number << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}