#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为例,搜索树为
1
1 2 4 8
1 1 3 1 3 9 1 3 9 27
下一层的幂小于上一层
*/
51nod 1060 最复杂的数(反素数)
最新推荐文章于 2021-09-14 20:00:00 发布