大家都很强, 可与之共勉 。
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
首先明确几个结论 :
一个数约数个数=所有素因子的次数+1的乘积
一个2000000000以内的数字不会有超过12个素因子
较小的数的指数一定大于等于较大的数的指数
然后通过计算得出一个2000000000以内的数字不会有超过12个素因子
所以
准备工作: 预处理出前12个素数.
然后就可以暴搜了, 将递归层数设定为第 dep 个素数. 枚举该素数选择多少个, 下一层的素数一定不会超过这个值.
当dep == 12时更新答案并返回. 如果当前数大于当前答案并且因数个数多于答案, 更新答案; 如果当前数小于答案但是因数个数多于答案, 那么也要更新, 因为原有答案不再合法.
# include <cctype>
# include <cstdio>
# define By_Lazer int main ( ) { return 0 ; }
const int prime [] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 33 } ;
struct IO {
char buf [1 << 20], *s, *t, ch ;
inline char pick ( ) {
return ( s == t ) ? ( t = buf + fread ( s = buf, 1, 1 << 20, stdin ), *s ++ ) : ( *s ++ ) ;
}
int x ;
inline operator int ( ) {
while ( ! isdigit ( ch = pick ( ) ) ) ;
for ( x = -48 + ch ; isdigit ( ch = pick ( ) ); x = x * 10 + ch - 48 ) ;
return x ;
}
} Read ;
class Main {
public :
int ans, tot, n ;
inline void Dfs ( int k, long long cur, int cnt, int last ) {
if ( k == 12 ) {
if ( ( cur > ans && cnt > tot ) || ( cur <= ans && cnt >= tot ) ) { ans = cur ; tot = cnt ; }
return;
}
int t = 1 ;
for ( int i = 0 ; i <= last ; ++ i ) {
Dfs ( k + 1, cur * t, cnt * ( i + 1 ), i ) ;
t *= prime [k] ;
if ( cur * t > n ) break ;
}
}
Main ( ) {
n = Read ;
Dfs ( 0, 1, 1, 20 ) ;
printf ( "%d\n", ans ) ;
}
} Z ;
By_Lazer