1748. The Most Complex Number/LG的数学计划~~~持续更新ing(反素数求解)

神奇的反素数, 首先定义

g(x) = x的约数个数

而反素数就是对于任意的0 < j < i 有g(j) < g(i)那么就称i为反素数
那么从这个定义中可以发现的是, 反素数一定是由连续的质数相乘
即对于反素数x一定有x=2^t1*3^t2*5^t3…………..
注意一定要是连续的, 即t1, t2, t3, t4, t5……>0;
好吧说的不清楚, 给百度百科的说明

对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数·
性质一:一个反素数的质因子必然是从2开始连续的质数.
性质二:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....

对于这个证明, 自己yy了一下(有不对的话请读者指出, 高中狗):

  • 设x的最小质因数不是2, 那么把其最小的质因数变成2得到新数x’
    易知x’一定小于x而约数个数和x相等, 矛盾 得证
  • 同理我们对于第二个性质若i < j && ti >= tj 我们又可以把ti, tj两个指数换一个顺序得到的新数一定比原数小且约数相等, 矛盾, 得证
    那么下面是一道反素数的经典例题,
    给出T(T∈[1,100]) 每组数据输入一个整数n(n∈[1,10^18])
    求小于等于n的 约数最多的 最小数;

典型的模板不多说给出代码(根据上面的性质搜索剪枝得到)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define rep(i, s, t) for(int i = s; i <= t; ++i)

typedef long long ll;
ll prime[30], res = 0, res_cnt, n;

void dfs(ll dep, ll t, ll cnt, ll la) {
    if(res_cnt < cnt) res = t, res_cnt = cnt;
    if(t < res && res_cnt <= cnt) res = t, res_cnt = cnt;
    ll temp = 1;
    rep(i, 1, la) {
        temp *= prime[dep];
        if(n/temp < t) break;//避免乘法爆ll
        dfs(dep+1, t*temp, cnt*(i+1), i);
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("data.in", "r", stdin);
    freopen("result.out", "w", stdout);
#endif
    int t = 1, _;
    prime[t] = 2;
    for(ll i = 3; i <= 0x3f3f3f && t <= 30; ++i) {
        bool flag = false;
        for(int j = 2; (ll)j*j <= i; ++j)
            if(i % j == 0) {flag = 1; break;}
        if(!flag) prime[++t] = i;
    }
    cin >> _;
    while(_--) {
        res_cnt = 0;
        res = 0;
        scanf("%lld", &n);
        dfs(1, 1, 1, 30);
        cout << res << " " << res_cnt << endl;
    }
}
原文地址:https://www.cnblogs.com/pbvrvnq/p/8530162.html