题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6623
题意:一个质数p,找p质因子分解后,最小的 质因子次数
题解:
n先约去10^4内的质数因子,剩余为m,
剩余质数因子>10^4,则m最大的质数因子次数为4,几种可能为:m=p^4 m=p^2*q^2 m=p^3 m=p^2 ,除去前面几种m质因数分解,其他最小的质数因子次数都为1 :m=p*q*r*s,m=p^2*q*r,m=p^3*q...m=p^2*q,m=p*q,m=q
ps:在m开三次方的时候,用p=pow(m,1/3)有精度差,可以用差小于1e-6,或 二分(1~pow(m,1/3)+1)来找p。
官方题解:
Let's first factorize N using prime numbers not larger than N1/5. And let's denote M as the left part, all the prime factors of M are larger than N1/5. If M=1 then we are done, otherwise M can only be P2, P3, P4 or P2*Q2, here P and Q are prime numbers.
(1) If M1/4 is an integer, we can know that M=P4. Update answer using 4 and return.
(2) If M1/3 is an integer, we can know that M=P3. Update answer using 3 and return.
(3) If M1/2 is an integer, we can know that M=P2 or M=P2*Q2. No matter which situation, we can always update answer using 2 and return.
(4) If (1)(2)(3) are false, we can know that answer=1.
Since there are just O(N1/5/log(N)) prime numbers, so the expected running time is O(T*N1/5/log(N)).
AC代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e6+10; 5 ll prime[maxn],n,ans; 6 bool flag[maxn]; 7 int cntprime; 8 void getl(){ 9 cntprime=0; 10 for (ll i = 2; i <= 1e6; i++){ 11 if (!flag[i]) prime[++cntprime] = i; 12 for (int j = 1; j <= cntprime && prime[j] * i <= 1e6; j++){ 13 flag[i * prime[j]] = true; 14 if (i % prime[j] == 0) 15 break; 16 } 17 } 18 } 19 void work(){ 20 ans=1e18; 21 ll m=n,cnt,cnt1; 22 for(int i=1;i<=cntprime&&prime[i]<10000&&prime[i]<=m;i++){ 23 if(m%prime[i]==0){ 24 cnt=0; 25 while(m%prime[i]==0){cnt++;m/=prime[i];} 26 ans=min(ans,cnt); 27 if(ans==1) return ; 28 } 29 } 30 31 if(m>1){ 32 cnt=sqrt(m); 33 if(cnt*cnt==m){ 34 cnt1=sqrt(cnt); 35 if(cnt1*cnt1==cnt){if(ans>4)ans=4;} 36 else if(ans>2){ans=2;} 37 } 38 else { 39 double q=pow(m,1.0/3.0); 40 if(abs(q-ceil(q))<abs(q-floor(q)))cnt=ceil(q); 41 else cnt=floor(q); 42 if(cnt*cnt*cnt==m&&ans>3){ans=3;return ;} 43 ans=1;return ; 44 } 45 } 46 } 47 int main(){ 48 ll T; 49 scanf("%lld",&T); 50 getl(); 51 while(T --){ 52 scanf("%lld",&n); 53 if(n<1e6&&!flag[n]){ 54 printf("1 "); 55 continue; 56 } 57 work(); 58 printf("%lld ",ans); 59 } 60 return 0; 61 }