反素数 -数学+搜索

反素数

Solution:

引理一:

1N中最大的反质数为,就是1N中约数最多的数里最小的一个

引理二:

若把最大的反质数x质因数分解:

[x=(p1^{c1})*(p2^{c2})*......*(pk^{ck}) ]

若p1≤p2≤......≤pk,那么一定满足:c1≥c2≥......≥ck

证明略。

同时注意到N只有2e9,那么这意味着任何一个数都有不超过10个质因子(最小的10个质因子相乘>2e9)

所以可以直接dfs,枚举每一个质因子的指数,且使之满足引理二、乘积不超过N。

在以上限制下,搜索量不大,每搜到一个数就更新一下ans即可。

Code:

#include <bits/stdc++.h>
#define RG register
#define IL inline
#define int long long 
using namespace std;

IL int gi(){
    char ch=getchar(); int x=0,q=0;
    while(ch<'0'||ch>'9') q=ch=='-'?1:q,ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return q?-x:x;
}

const int INF=2147483647;

int n,tot,ans=INF,pr[11]={0,2,3,5,7,11,13,17,19,23,29},cnt[11];

IL int check() {
    RG int i,sum=1;
    for (i=1;i<=10&&cnt[i];++i) sum*=(cnt[i]+1);
    if (sum>tot) return tot=sum,1;
    if (sum==tot) return 2;
    return 0;
}

void DFS(int x,int now) {
    RG int i,fl;
    if (x==11) {
        if ((fl=check())!=0) {
            if (fl==1) ans=now;
            else ans=min(ans,now);
        }
        return;
    }
    for (i=cnt[x-1];i>=0;--i)
        if (now*pow(pr[x],i)<=n)
            cnt[x]=i,DFS(x+1,now*pow(pr[x],i)),cnt[x]=0;
}

signed main() {
    n=gi(),cnt[0]=30,DFS(1,1);
    printf("%lld
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Bhllx/p/10653158.html