2019HDU多校Minimal Power of Prime——分段讨论&&思维

题目

将 $n$($1 < n \leq 10^{18}$)质因数分解,求质因数幂的最小值。

分析

直接质因数分解,不太行。

可以这样想,对小区间质因数分解,n变小了,再枚举答案。

打印1-10000之间的素数表然后质因数分解,分解完剩下的那个数,

  • 两种质数(肯定大于 $10^4$)相乘,最多二次,合起来也是一个平方数;
  • 三种或以上质数相乘,只可能为一次,不用考虑。
  • 一种质数,最多为四次方,枚举四、三、二次方,如果都不是,就是单个质数

要注意:先看是4次方再看2次方(因为如果满足4次方一定满足2次方,但是满足4次方也满足2次方,2次方的话就不是质因数了),3次方无所谓,因为开3次方会损失精度,所以就二分一下。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
ll n;

//返回n以内素数的个数
//埃氏筛法O(nloglogn)
const int maxn = 100000 + 10;
int prime[maxn];            //prime[i]表示第i个素数
bool is_prime[maxn + 1];    //is_prime[i]为true表示i是素数

int sieve(int n)
{
    int cnt = 0;
    for (int i = 0; i <= n; i++)  is_prime[i] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2; i <= n; i++)
    {
        if (is_prime[i])
        {
            prime[cnt++] = i;
            for (int j = i * i; j <= n; j += i)  is_prime[j] = false;  //i * i可能爆int
        }
    }
    return cnt;
}

bool is_three(ll n)    //是否能开立方
{
    ll l = 10000, r = 1e6;
    while(l <= r)
    {
        ll mid = (l+r) >> 1;
        ll tmp = mid*mid*mid;
        if(tmp == n)  return true;
        else if(tmp > n) r = mid-1;
        else l = mid+1;
    }
    return false;
}

int main()
{
    int cnt = sieve(10000);  //筛出10000内的质数
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld", &n);
        int ans = 100;
        for(int i = 0;i < cnt;i++)
        {
            if(n % prime[i] == 0)
            {
                int tmp = 0;
                while(n % prime[i] == 0)
                {
                    n /= prime[i];
                    tmp++;
                }
                ans = min(tmp, ans);
            }
            if(n == 1) break;
        }
        if(ans == 1){ printf("1\n"); continue;}
        if(n == 1){ printf("%d\n", ans); continue;}

        ll t1 = (ll)sqrt(n);
        ll t2 = (ll)sqrt(t1);
        if(t2*t2*t2*t2 == n)  ans = min(ans, 4);
        else if(t1*t1 == n)  ans = min(ans, 2);
        else if(is_three(n))  ans = min(ans , 3);
        else ans = min(ans, 1);
        printf("%d\n", ans);
    }
    return 0;
}

参考链接:https://blog.csdn.net/lgz0921/article/details/97948432

猜你喜欢

转载自www.cnblogs.com/lfri/p/11290356.html