反素数概念:
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
性质有两条:
性质(1)一个反素数的所有质因子必然是从2开始的连续若干个质数,因为反素数是保证约数个数为的这个数尽量小
性质(2)同样的道理,如果,那么必有
常用题型:
(1)给定一个数,求一个最小的正整数,使得的约数个数为
(2)求出中约数个数最多的这个数
例题:
链接:https://ac.nowcoder.com/acm/problem/19967
来源:牛客网
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。如果某个正整数x满足:g(x) > g(i) 0 < i < x ,则称x为反质数。
例如,整数1,2,4,6等都是反质数。现在给定一个数N,你能求出不超过N的最大的反质数么 ?
输入描述:
一个数N(1 ≤ N ≤ 2,000,000,000)。
输出描述:
不超过N的最大的反质数。
示例1
输入
复制
1000
输出
复制
840
由数据范围,预处理前面的一些素数即可
利用dfs搜索,由性质二进行了一些剪枝优化
#include<bits/stdc++.h>
using namespace std;
const int INF=INT_MAX;
const long long LLINF=LONG_MAX;
const int mod=1e6+3;
typedef long long ll;
int prime[20]={0,2,3,5,7,11,13,17,19,23,29,31};
int cot1,cot2; //cot1记录n最多由几个素数相乘,cot2记录素数的指数最多为多少
ll ans1,ans2,n; //ans1记录因子的个数,ans2记录小于n的最大的反素数
void dfs(int k,int sum,int num,int z) //k记录当前是第几个素数,sum记录当前的数,num记录素数的个数,z记录因子的个数
{
if(k==1+cot1) //搜到最后一个素数
{
if(z>ans1) // 如果最后因子的个数大于ans1,就更新ans1和ans2
{
ans1=z;
ans2=sum;
}
if(z==ans1&&(ans2>sum)) //更新ans2为最大值
ans2=sum;
return ;
}
for(int i=0;i<=num;i++)
{
if(sum*pow(prime[k],i)>n) //如果结果比n大,就没有继续搜的必要了,直接break
break;
dfs(k+1,sum*pow(prime[k],i),i,z*(i+1)); //由性质2得第三个参数没有必要为num,只要下一个搜索到i即可
}
}
int main()
{
cin>>n;
ll m=n;
while(m)
{
m/=prime[++cot1];
}
m=n;
while(m)
{
m/=2;
cot2++;
}
dfs(1,1,cot1,1);
cout<<ans2<<endl;
return 0;
}