【题解】2019,4.25模拟赛(Reward)
\(Description:\)
给出一个 \(n\) ,求约数个数是 \(n\) 的最小整数。
\(Sample\) \(Input:\)
4
\(Sample\) \(Output:\)
6
\(Hint:\)
1<=n<=50000
\(Solution:\)
一眼数论,是吧?
考虑约数个数我们是有公式的,唯一分解定理,
约数个数 \(x=\prod_{i=1}^{i<=cnt} (1+c_i)\) 。
那么dfs枚举质数的指数。
这样应该挺暴力的,也应该拿不了几分,考虑剪枝:
- 最优性:如果当前组成的数比答案大,退出
- 上下界:为了保证答案最小,每次枚举上界可以从上一次的次数
- 上下界:发现最多只要15个质数就可以使约数个数达到50000.
最后最强剪枝:
压位高精。。。
代码,调了我一晚上。。。吐血。
#include<cstdio>
#include<iostream>
#include<cstring>
using std::scanf;
using std::printf;
using std::getchar;
using std::putchar;
using std::min;
typedef long long LL;
const int N=4000+5,M=50000+5,INF=0x3f3f3f3f;
const LL A=100000000;
int n,cnt=15;
int a[]={0,2,3,5,7,11,13,17,19,23,29,31,33,37,41,43};
struct bigint {
int n;
LL a[N];
inline void clear() { memset(a,0,sizeof(a)),n=0;}
inline void work1() { while(!a[n] && n>1) n--;}
inline void work2() { while(a[n]) n++,a[n]=a[n-1]/A,a[n-1]%=A;}
inline bigint write() const {
printf("%lld",a[n]);
for(int i=n-1;i>=1;--i) printf("%08lld",a[i]);
return *this;
}
inline bigint operator = (const LL &nt) {
LL tmp=nt;
while(tmp>0) a[++n]=tmp%A,tmp/=A;
return *this;
}
inline bool operator < (const bigint &nt) const {
if(n!=nt.n) return n<nt.n;
for(int i=n;i>=1;--i)
if(a[i]!=nt.a[i]) return a[i]<nt.a[i];
return false;
}
inline bool operator > (const bigint &nt) const {
return nt<(*this);
}
inline bool operator != (const bigint &nt) const {
return ((*this)<nt) || ((*this)<nt);
}
inline bool operator == (const bigint &nt) const {
return !((*this)!=nt);
}
inline bigint operator * (const LL &nt) const {
bigint tmp; tmp.clear();
tmp.n=n+1;
for(int i=1;i<=n;++i){
tmp.a[i]+=a[i]*nt;
tmp.a[i+1]+=tmp.a[i]/A;
tmp.a[i]%=A;
}
for(int i=1;i<=n;++i){
tmp.a[i+1]+=tmp.a[i]/A;
tmp.a[i]%=A;
}
tmp.work2();
tmp.work1();
return tmp;
}
inline bigint operator * (const bigint &nt) const {
bigint tmp; tmp.clear();
tmp.n=nt.n+n;
for(int i=1;i<=n;++i) for(int j=1;j<=nt.n;++j){
tmp.a[i+j-1]+=a[i]*nt.a[j];
tmp.a[i+j]+=tmp.a[i+j-1]/A;
tmp.a[i+j-1]%=A;
}
for(int i=1;i<=tmp.n;++i){
tmp.a[i+1]+=tmp.a[i]/A;
tmp.a[i]%=A;
}
tmp.work2();
tmp.work1();
return tmp;
}
}ans,b;
void dfs(int k,int num,bigint now,int pre){
if(now>ans && ans.n!=0) return;
if(k>=cnt+1) return;
if(num==n){
if(ans.n==0 || ans>now) ans=now;
return;
}
bigint ret; ret.clear();
ret=a[k];
for(int i=1;i<=pre;++i){
if(num*(i+1)>n) break;
if(n%(i+1)==0) dfs(k+1,num*(LL)(i+1),now*ret,i);
ret=ret*a[k];
}
}
int main(){
b=1;
scanf("%d",&n);
dfs(1,1,b,n);
ans.write();
return 0;
}