题目
http://www.lydsy.com/JudgeOnline/problem.php?id=1053
1053: [HAOI2007]反素数ant
Time Limit: 10 Sec Memory Limit: 162 MB
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
题解
数x的约数个数的求法:
将数x质因数分解
x=p1^a1*p2^a2*p3^a3….
x的约数个数即为
(a1+1)(a2+1)(a3+1).. //+1是因为某质因子对某约数的贡献范围为 0~a反素数的性质:
性质一:一个反素数的质因子必然是从2开始连续的质数.
性质二:p=2^t1*3^t2*5^t3*7^t4…..必然t1>=t2>=t3>=….
(性质二约束了性质一)
对于性质二的证明:
对于数x
如果存在ti < tj && i>j
那么将ti,tj交换,得到数y,
xy约数个数相同,且y < x,由定义可知,y是反素数,x不是(定义中不存在 = 情况)
在n的取值范围内,素数个数不超过12个
实际上>2*3*5*7*11*13*17*19*23*29 就已经超过n的范围
爆搜,枚举每个素数的次数,更新答案即可
代码
#include<iostream>
#include<cstdio>
using namespace std;
#define LL long long
int prime[]={1,2,3,5,7,11,13,17,19,23,29,31,37};
LL ans,tot,n;
void dfs(LL now,LL cnt,LL maxx,LL num){
// 当前数字大小 第几个素数 次数限制 约数个数
if(now>n) return ;
if(num>tot||tot==num&&now<ans){//更新答案
tot=num,ans=now;
}
LL tmp=now;
for(int i=1;i<=maxx;i++){
if(tmp*prime[cnt]<=n){
tmp*=prime[cnt];
dfs(tmp,cnt+1,i,num*(i+1));
}
}
}
int main(){
cin>>n;
dfs(1,1,32,1);
cout<<ans;
return 0;
}
丢一个题解比较详细的链接
http://blog.csdn.net/qq_36693514/article/details/78273235#t5