题目链接: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 ",solve(n)); } return 0; }