Description
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。如果某个正整数x满足:g(x)>g(i)
,则称x为反质数。例如,整数1,2,4,6等都是反质数。现在给定一个数N,你能求出不超过N的最大的反质数么
?
Input
一个数N(1<=N<=2,000,000,000)。
Output
不超过N的最大的反质数。
Sample Input
1000
Sample Output
840
解题思路:
结论一:
一个数约数个数=所有素因子的次数+1的乘积
结论二:
一个2000000000以内的数字不会有超过12个素因子
结论三:
较小的数的指数一定大于等于较大的数的指数
有了以上3个结论这个题就是水题了。。
准备工作: 预处理出前12个素数。
然后就可以暴搜了, 将递归层数设定为第 dep 个素数. 枚举该素数选择多少个, 下一层的素数一定不会超过这个值。
当dep == 12时更新答案并返回. 如果当前数大于当前答案并且因数个数多于答案, 更新答案; 如果当前数小于答案但是因数个数多于答案, 那么也要更新, 因为原有答案不再合法。
代码如下:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n;
int ans = 1, num = 1; //数的大小, 约数个数
int pri[15] = {1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
void dfs(int dep, LL now, int cnt, int limit){ //第dep层素数,当前数大小,约数的个数,该素数选多少
if(dep == 12){
if(now > ans && cnt > num) {ans = now; num = cnt;}
if(now <= ans && cnt >= num) {ans = now; num = cnt;}
return;
}
LL t = 1;
for(int i = 0; i <= limit; i++){
dfs(dep + 1, now * t, cnt * (i + 1), i);
t *= pri[dep];
if(now * t > n) break;
}
}
int main(){
scanf("%lld", &n);
dfs(1, 1, 1, 30);
printf("%d\n", ans);
return 0;
}