【题解】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;
}

posted @ 2019-04-25 22:07  章鱼那个哥  阅读(121)  评论(0编辑  收藏  举报