51nod 1060 最复杂的数(反素数)

来源:互联网 发布:站长工具查询端口 编辑:程序博客网 时间:2024/06/05 05:12
#include<cstdio>using namespace std;/*求[1,n]中约数最多的数和约数的个数 (1<=n<=e^18)反素数对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数性质一:一个反素数的质因子必然是从2开始连续的质数性质二:m=2^s1*3^s2*5^s3*7^s4.....必然s1>=s2>=s3>=....*/const int maxn=1e3+5;typedef long long LL;int p;int prime[maxn];int is_prime[maxn];LL n,ans;int sum;//素数筛,预处理素数void sieve(int n){    for(int i=0;i<n;i++)    {        is_prime[i]=1;    }    is_prime[0]=is_prime[1]=1;    p=0;    for(int i=2;i<=n;i++)    {        if(is_prime[i])        {            prime[p++]=i;            for(int j=2*i;j<=n;j+=i)            {                is_prime[j]=0;            }        }    }}void dfs(int prime_id,int pre_index,LL temp,int num){//prime_id枚举到第id个素数  pre_index质因数幂的上限//temp枚举到当前的数  num这个数约数个数//如果约数个数更多,将最优解更新    if(num>sum)    {        sum=num;        ans=temp;    }//如果约数个数相同,将最优解更新为较小的数    if(num==sum&&ans>temp)    {        ans=temp;    }    if(prime_id>=16)//只需要用到前面10多个素数    {        return ;    }    for(int i=1;i<=pre_index;i++)//枚举每个质因子的个数    {       if(temp<=n/prime[prime_id])//这里最好用除法判断,乘法会溢出LL       {           temp*=prime[prime_id];//更新枚举的数           dfs(prime_id+1,i,temp,num*(i+1));//继续搜索       }    }}int main(){    int T;    sieve(maxn);    scanf("%d",&T);    while(T--)    {        scanf("%lld",&n);        ans=1,sum=1;        dfs(0,64,1,1);//搜索起点设定        printf("%lld %d\n",ans,sum);    }    return 0;}/*以g(12)=6为例,搜索树为             11       2        4          81     1   3    1 3 9    1  3  9  27下一层的幂小于上一层*/