Given the number n, find the smallest positive integer which has exactly n divisors. It is guaranteed that for the given n the answer will not exceed 1e18.
Input
The first line of the input contains integer n (1 ≤ n ≤ 1000).
Output
Output the smallest positive integer with exactly n divisors.
题目大意:
给定一个数字n,找到具有n个因子的最小整数.
思路:
由于答案达到了1e18,因此不可以暴力。
考虑到质因子分解定理,最后的答案肯定能分解成,而n等于
题目要求找到最小的ans,我们贪心的选取两个数a和b,保证这两个数的n值相同,则局部最优解一定会在min{a,b}中诞生,而两个数中较小的那个数有什么特点呢?
举个例子:12和18存在相同的n,但是,而,注意到指数的选择上有所不同,前者是2 2 3,后者是2 3 3,而答案显而易见是12.由此可见,如果n相同,那么指数的底数要尽可能小。
于是想到了:我们可以从底数2开始枚举指数,然后往下搜索新的质数底数,更新当前的因子数与n比较,然后更新最小值即可。
#include<bits/stdc++.h>
#define int long long
#define rd(x) scanf("%lld",&x)
#define put(x) printf("%lld",x)
#define YES "YES"
#define NO "NO"
#define Yes "Yes"
#define No "No"
#define mod 1000000007
#define MAX 2147483647
#define MIN -MAX
using namespace std;
const int N = 2e5+5;
int ans= ((int)1<<62);
int prime[30]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53};
void dfs(int depth,int temp,int num,int po,int n){
//之所以素数选到53,是因为当底数枚举到53的时候,此时的答案值已经到达数据范围了
//为什么会到达数据范围?
//每次枚举后面的底数,他的指数一定会小于前面的素数的指数
//可以像12和18的例子一样转移指数的位置
//当前数字的指数已经超过n了,跳过
if(depth>=16 || num>n){
return;
}
//更新最小ans
if(num==n && temp<ans){
ans=temp;
return;
}
//枚举当前底数的指数
for(int i=1;i<=po;i++){
//剪枝,若新数字已经大于当前最小值,则不需要继续下去了;
//因为继续下去的答案一定也会大于当前最小值
if(temp * prime[depth]>ans){
break;
}
temp = temp*prime[depth];
dfs(depth+1,temp,num*(i+1),i,n);
}
}
void solve(int n){
dfs(0,1,1,64,n);
}
signed main(){
int T=1;
// rd(T);
while(T--){
int n;
rd(n);
solve(n);
cout<<ans;
}
return 0;
}