51nod1060(最复杂的数)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1060

对于一个合数 x ,分解质因数为 x = p1^a1 * p2^a2 *……*pk^ak;

从这些质因子里面选出一些乘起来,就是 x 的一个因子,假设为 y ;

对于这个合数的每一个质因子,都有 a1+1 种选择(选出0个、1个、2个……a1个该因子乘到 y 里面);

那么 x 的因子个数就是 (a1+1)*(a2+1)*……*(ak+1);

x 的因子个数尽量多就是让 ai 的成绩尽量大,由于还要 <=n ,那么 pi 就得尽量小,所以从素数表中从小到大选取素数,对于每一个素数,分配一个尽量大的ai,进行搜索。

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

typedef unsigned long long LL;
const int maxn = 1e6 + 10;

LL prime[maxn];
LL ksmA[78500][64];
LL n;
LL ans;
LL cnt = 1;

void init(){
    prime[0] = 1;
    prime[1] = 2;
    for (LL i=3; i<=maxn; i+=2){
        if (!prime[i]){
            prime[++prime[0]] = i;
            prime[i] = 1;
            LL j = i * 2;
            while (j <= maxn){
                prime[j] = 1;
                j += i;
            }
        }
    }
    for (int i=0; i<prime[0]; i++){
        ksmA[i][0] = 1;
        int k = log(1e18) / log(prime[i]);
        for (int j=1; j<=k; j++){
            ksmA[i][j] = ksmA[i][j-1] * prime[i];
        }
    }
}

void dfs(int step, LL x, LL cnt_, int last){

    if (cnt_ > cnt || (cnt_ == cnt && x < ans)){
        cnt = cnt_;
        ans = x;
    }
    if (x > ans) {
        return;
    }

    for (LL i=last; i>=1; i--){
        LL factor = ksmA[step][i];
        if (factor == 0) continue;
        if (n / x >= factor)
            dfs(step+1, x*factor, cnt_*(i+1), i);
    }
}

int main()
{
    int t;
    init();

    scanf("%d", &t);
    while (t > 0){
        t--;

        scanf("%lld", &n);
        ans = n;
        cnt = 0;
        LL last = log(n) / log(2) + 1;
        dfs(1, 1, 1, last);
        cout << ans  << " " << cnt << endl;
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qust1508060414/article/details/76375904