2019杭电多校赛第四场 HDU6623 Minimal Power of Prime 素数

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6623

题意:输出将一个数n(1e18)质因数分解后其所有质因数幂的最小值

分析:首先,质因数分解中,一个数的所有质因数都会参与构成这个数

n最大是1e18的情况下,单独处理前1e4的,前1e4的处理完后如果发现n还不是1,说明它还有质因数,而且这个质因数肯定是大于1e4的了,而大于1e4的质因数幂取值就只有4,3,2,1这四种了,分别看n^(1/4),n^(1/3),n^(1/2)是不是整数就好,如果都不是就肯定是1了。

简而意之,先处理1e4以内的质数,也就1000多个,然后如果没有除尽的话,因子最多也就4个了,所以幂数大于1的情况有p1^4,p1^3, p1^2 , p1^2*p2^2,  对于其他情况肯定有幂为1的。

代码有较为详细的注释

另外推荐一个快速质因数分解的方法,本题没用到,但还是很有用的https://blog.csdn.net/Asher_S/article/details/81867146

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=1e4+7;
const ll inf=1e18+7;
const double pi=acos(-1);
int num,pri[maxn];
void init(){//这个函数用来求1e4的质数有哪些 
    int lim;
    for(int i=2;i<maxn;i++){
        if(!pri[i]) pri[num++]=i;
        for(int j=0;j<num;j++){
            lim=i*pri[j];
            if(lim>=maxn) break;
            pri[lim]=1;
            if(i%pri[j]==0) break;
        }
    }
}
ll three(ll n){
    ll l=1,r=pow(n*1.0,1.0/3)+1,mid;
    while(l<=r){
        mid=(l+r)>>1;
        if(mid*mid*mid==n) return mid;
        else if(mid*mid*mid>n) r=mid-1;
        else l=mid+1;
    }
    return -1;    
}

ll solve(ll n){
    int ans=100,res;//ans用来记录最后结果,初始化大一点 
    for(int i=0;i<num;i++){
        if(1ll*pri[i]*pri[i]>n)break;//说明接下来的质因数不可能是n的质因数了 
        if(n%pri[i]==0){
            res=0;
            while(n%pri[i]==0){
            res++;
            n/=pri[i];
            }
            ans=min(ans,res);
        }
        if(ans==1) return 1;//如果在这一步便取到了最小值1,1e4之后的数据就不用管了,直接返回 
    }
    //这个循环求出了n的四分之一次幂前的质因数的答案,接下来开始求剩下的部分,剩下部分不可能超过四次幂,
    //因为他们都大于1e4,即便n取最大1e18也顶多四次 
    if(n>1){//n不为1说明其还有质因数,且1e4前面的都已经处理了,只能是1e4后的质因数 
        ll kg1=sqrt(n),kg2;//判断是否为整数 
        if(kg1*kg1==n){
            kg2=sqrt(kg1);
            if(kg2*kg2==kg1){
                if(ans>4) ans=4;
            }
            else if(ans>2) ans=2;
        }
        else{
            kg1=three(n);//求出三次根号下的n 
            if(kg1*kg1*kg1==n&&ans>3) ans=3;
            else ans=1;//都不满足的话就为1 
        }
    }
    return ans;
}
int main(){
    int T;cin>>T;
    init(); 
    while(T--){
        ll n; scanf("%lld",&n);
        printf("%lld\n",solve(n));
    }
    return 0;
}

 

posted @ 2019-08-01 09:32  清酒令  阅读(312)  评论(2)    收藏  举报