[SDOI2005]反素数ant

原题链接:https://www.luogu.org/problemnew/show/P1463

题目大意:在[1,n]的范围内,求一个数,要求所有小于这个数的数因数个数也要小于这个数,n<=2e9

设m=a1^p1*a2^p2……ak^pk

m的约数个数为(p1+1)*(p2+1)……(pk+1)

luogu题解上的dalao们都没给证明,但是其实很好证啊。。。

设num是m的一个因数,可以有0,1...pi个ai算进num中,即有pi+1种选法,因为ai都是质因数,所以互不影响,所以实际因数个数就是个乘法原理。。。

因为2^31>2e9 所以p1+p2+...pk<31

能够证明,符合条件的数字,它的质因数分解一定是由a1开始连续的

num=a1^p1*a2^p2...ak^pk  (p1*p2*p3*...*pk>0)

因为如果不是这样,则必定有一个数,将其中的一个ai换为更小的pi=0的ai,num一定会变小,但是(p1+1)*(p2+1)……(pk+1)却不会变,原数不合要求。

而最多10个质因子的乘积就会超过2e9,所以枚举质因子时只需枚举10个就够了。(不过为了保险,我用了15个)

然后枚举选用的质因子和它们的指数,搜索即可。

#include<cstdio>
int pre[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
long long n,maxn,ans,sum;
void dfs(long long p,long long a,int x)
{
    if(p>maxn)
    {
        maxn=p;
        ans=a;
    }
    if(p==maxn&&ans>a) ans=a;
    if(x>15) return;
    for(int i=1;i<=34;i++)
    {
        if(a*pre[x]>n) break;
        dfs(p*(i+1),a*pre[x],x+1);
        a*=pre[x];
    }
}
int main()
{
    scanf("%lld",&n);
    ans=n;
    dfs(1,1,1);  
    printf("%lld",ans);
    return 0;
}

 

posted @ 2018-01-23 20:47  Excim  阅读(131)  评论(0编辑  收藏  举报