AcWing 198. 反素数

思路

  1. 求1-N中的反素数,实际上就是找出1-N中约数最多的数字,如果这个数字有 1个,取最小的一个。
  2. 记这个数字为x,可以分解质因数 x = p 1 c 1 p 2 c 2 . . . . p n c n x =p_1^{c_1}p_2^{c_2}....p_n^{c_n} x=p1c1p2c2....pncn,且 p 1 < p 2 < . . . < p n p_1<p_2<...< p_n p1<p2<...<pn
  3. 由于 2 ∗ 3 ∗ 5 ∗ 7 ∗ 9 ∗ 11 ∗ 13 ∗ 17 ∗ 19 ∗ 23 > 2 31 − 1 2*3*5*7*9*11*13*17*19*23 > 2^{31}-1 235791113171923>2311,所以不同的质因子个数最多是9个,且 x x x的质因子必定是从最小的9个质数里面选(反之则可以把任意一个质数替换成更小的质数,矛盾!),所以最多只有9个不同的选择,可以用dfs来写。
  4. 对于2中的表达式,对于任意 i > 1 i>1 i>1,有 c i − 1 > c i c_{i-1}>c_i ci1>ci。(若 c i − 1 < c i c_{i-1} < c_{i} ci1<ci p i − 1 c i − 1 p i c i p_{i-1}^{c_{i-1}}p_i^{c_i} pi1ci1pici可以替换成 p i − 1 c i p i c i − 1 p_{i-1}^{c_i}p_i^{c_{i-1}} pi1cipici1,此时约数个数相同,但可以把x变成一个更小的一个数 y y y,这与 x x x是最小的数矛盾!)
  5. 综上所述,只需要利用最小的9个质数暴搜,外加第4部分析的剪枝就可以了

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>

typedef long long LL;

using namespace std;
int n;
//最小的9个质数
int primes[] = {2, 3, 5, 7, 11, 13, 17, 19, 23};
//maxd最大约数个数,number为这个数字
int maxd, number; 

//u为p的下标,c是上一个质数的指数,p是当前的数字,s是当前数字的约数个数
void dfs(int u, int c, int p, int s) {
    if(u == 9) return;
    if(s > maxd || s == maxd && p < number) {
        number = p;
        maxd = s;
    }
    
    //依次选1-c个质数
    for(int i = 1; i <= c; i++) {
        if((LL)p * primes[u] > n) return;
        p *= primes[u];
        dfs(u + 1, i, p, s * (i + 1));
    }
}

int main()
{
    cin >> n;
    dfs(0, log(n), 1, 1);
    cout << number;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值