BZOJ1053: [HAOI2007]反素數ant

Description
對於任何正整數x,其約數的個數記作g(x)。例如g(1)=1、g(6)=4。如果某個正整數x滿足:g(x)>g(i)(0<i<x) ,則稱x爲反質數。例如,整數1,2,4,6等都是反質數。
現在給定一個數N,你能求出不超過N的最大的反質數麼?
Input
一個數N(1<=N<=2,000,000,000)。
Output
不超過N的最大的反質數。
Sample Input
1000
Sample Output
840
HINT
Source

轉變一下思路,該題等價於不超過n的數中約數最多的數中的最小數(即若約數相等則取較小,因爲題目要求是g(x)嚴格大於g(i)),利用反素數的一個性質:

一個反素數的所有質因子必然是從2開始的連續若干個質數

(應該還算比較好理解吧……自己想想就知道了)
所以本題就可以用遞歸來解決了。

#include<cstdio>
#define INT_MAX 2147483647
using namespace std;
int n,ans,ans1;
int p[16]={1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};//連續的素數
void read(int &x)
{
    char t=getchar();x=0;int f=1;
    while ((t<48)or(t>57)){if(t=='-')f=-1;t=getchar();}
    while ((t>=48)and(t<=57)){x=x*10+(int)t-48;t=getchar();}
    x*=f;
}
void dfs(int dep,int tmp,int num)
//dep表示深度,即p數組的一個指針,依次枚舉
//tmp記錄當前得到的數
//num表示tmp的約數個數
{
    if (dep>=16) return;
    if (num>ans1){ans1=num;ans=tmp;}//約數更多
    if ((num==ans1)and(tmp<ans)and(tmp<=n)) ans=tmp;//取較小值,防止相等
    for (int i=1;i<=31;++i)//log2(2000000000)≈31,枚舉p[dep]的i次方
    {
        if (n/p[dep]<tmp) break;
        dfs(dep+1,tmp*=p[dep],num*(i+1));//遞歸
    }
}
int main()
{
    read(n);
    ans=INT_MAX;
    dfs(0,1,1);
    printf("%d",ans);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章