题目大意:给你一个数n,把它分解为素数的幂次的乘积的形式:n=p1^e1 * p2^e2 * .......pk^ek  求最小的幂次是多少

n=le18

分析:

首先我们肯定是不可以枚举1e18的因子的,因为sqrt(1e18)=1e9 ,这样铁超时,那么1s的时间我们是可以预处理出10000以内的素数,我们首先得意思到n在10000以后的素数的幂都不可能大于5了,这很好理解(10001)^5>1e18 , 所以我们可以先用10000以内的素数算出一个最小幂 和剩余数Y, 在枚举看看后面可不可能出来4,3,2,1的幂; 这也很容易寻找,(Y^(1/4))^4==Y,就说明有4的幂 , 3,2,1同理,需要注意,在枚举3的幂的时候,sqrt()的精度会不行,所以需要二分逼近一下

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll pr[10010];
bool vis[10010];
int tot;
void init(){
    for(int i=2;i<10010;i++){
        if(vis[i]==0){
            pr[++tot]=i;
            for(int j=i*2;j<10010;j+=i)
                vis[j]=1;
        }
    }
}
bool fun(ll n){
    ll l=1,r=pow(n*1.0,1.0/3.0)+1;
    while(l<=r){
        ll mid=(l+r)>>1;
        if(mid*mid*mid==n) return 1;
        else if(mid*mid*mid>n) r=mid-1;
        else l=mid+1;
    }
    return 0;
}
int main(){
    init();
    int _; scanf("%d",&_);
    while(_--){
        ll n;
        scanf("%lld",&n);
        int ans=0x3f3f3f3f;

        for(int i=1;i<=tot;i++){
            if(pr[i]>n) break;

            int x=0;
            while(n%pr[i]==0){
                n/=pr[i];
                x++;
            }
            if(x!=0)
            ans=min(ans,x);
        }
       // cout<<n<<endl;
        if(n==1||ans==1) printf("%d\n",ans);
        else {
            ll m1=(ll)sqrt(sqrt(n*1.0)*1.0);
            ll m2=(ll)sqrt(n*1.0);
            if(m1*m1*m1*m1==n) ans=min(ans,4);
            else if(fun(n)) ans=min(ans,3);
            else if(m2*m2==n) ans=min(ans,2);
            else ans=1;
            printf("%d\n",ans);
        }
    }
}
View Code
01-19 13:20