1 条题解

  • 1
    @ 2023-11-29 10:53:59

    d(n)d(n)nn 的约数个数函数。

    显然求的是 i[1,n]i \in [1,n] 使得 d(i)d(i) 最大的 ii,如果有多个 ii 满足条件,取最小的 ii

    我们可以从大到小枚举约数个数 d(i)d(i),求最小的 ii,看 ii 是否在 1n1 \sim n 之间。

    考虑搜索。

    性质 11:根据贪心,我们一定是从小到大来选择质数。

    性质 22:我们知道 d(n)=i=1k(ci+1)d(n)=\prod_{i=1}^k (c_i+1),因此每个质数的次数+1一定是 d(i)d(i) 的约数。

    于是本题解决了。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int N=1e5+5;
    const LL inf=1e18;
    int v[N],prime[N],pr;
    void init(){
    	memset(v,0,sizeof(v));pr=0;
    	for(int i=2;i<N;i++){
    		if(!v[i])prime[++pr]=i;
    		for(int j=1;j<=pr&&i*prime[j]<N;j++){
    			v[i*prime[j]]=1;
    			if(i%prime[j]==0)break;
    		}
    	}
    }
    LL qpow(LL a,LL b){
    	LL ans=1;
    	while(b){
    		if(b&1)ans=ans*a;
    		a=a*a;b>>=1;
    	}
    	return ans;
    }
    LL ans,n;
    void dfs(int d,LL now,int pos){
    	if(now>n||now<=0)return;//>n是剪枝,<=0是溢出了,也要剪枝。
    	if(d==1){
    		ans=min(ans,now);
    		return;
    	}
    	for(int j=2;j<=d&&j<=n/prime[pos]+1;j++){
    		if(d%j==0){
    			dfs(d/j,now*qpow(prime[pos],j-1),pos+1);
    		}
    	}
    }
    int main(){
    	init();
    	scanf("%lld",&n);
    	if(n==1){
    		puts("1");
    		return 0;
    	}
    	for(int i=2500;i>=2;i--){
    		ans=inf;
    		dfs(i,1,1);
    		if(ans<=n){
    			printf("%lld",ans);
    			break;
    		}
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    1053
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    (无)
    递交数
    61
    已通过
    30
    上传者