BZOJ - 1053 HAOI2007 反素数

大家都很强, 可与之共勉 。

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值