https://codeforces.com/contest/27/problem/E
反素数:
若N <= 2 ^ 31
引理1: 1 ~ N 中的反素数,就是 1 ~ N中约数个数最多的数中 最小 的一个。
引理2: 1 ~ N 中任何数的不同质因子都不会超过 10 个且所有质因子的质数都不会超过 30。
引理3: x [ 1, N ],x 为反素数的必要条件是:x 分解质因数后可以写成
2^c1 + 3^c2 + 5^c3 + 7^c4 + 11^c5 + 13^c6 + 17^c7 + 19^c8 + 23^c9 + 29^c10, 且 c1 >= c2 >= c3 >= c4 >= c5 >= c6 >= c7 >= c8 >= c9 >= c10,
换句话说, x的质因子是连续的若干个最小的质数,并指数单调递减。
求法:
根据上面的三个引理,我们可以直接DFS,一次确认前 个质数的指数,并满足指数单调递减,总成绩不超过 ,同时记录约数的个 数即可。最后利用 引理1 找到约数个数最多的数里最小的那个数即可。
我们可以把当前走到每一个素数前面的时候列举成一棵树的根节点,然后一层层的去找。找到什么时候停止呢?
1. 当前走到的数字已经大于我们想要的数字了
2. 当前枚举的因子已经用不到了
3. 当前因子大于我们想要的因子了
4. 当前因子正好是我们想要的因子(此时判断是否需要更新最小 ans )
然后 dfs 里面不断一层一层枚举次数继续往下迭代
题目大意:
给你 一个正整数 n, 让你求一个拥有 n 个因子的最小正整数
思路:
即求因子数一定的最小反素数
代码实现:
#include <bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(0);
#define LL long long
#define ULL unsigned long long
#define INF ~0ULL
ULL p[16] = {2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
ULL n,ans;
// 枚举到的素数,当前因子的数量,当前因子总数,上一个素数的幂
void dfs(ULL depth, ULL temp, ULL num, ULL up)
{
if(num > n || depth >= 16) return;
if(num == n && ans > temp)
{
ans = temp; return;
}
for (ULL i = 1; i <= up; i ++ )
{
if(temp / p[depth] > ans) break;
dfs(depth + 1, temp *= p[depth], num * (i + 1), i);
}
}
void solve()
{
cin >> n;
ans = INF;
dfs(0, 1, 1, 64);
cout << ans << endl;
}
int main()
{
IOS
int T = 1;
//cin >> T;
while(T --)
{
solve();
}
return 0;
}