欧拉项目第三题之最大质数因子
13195的质数因子有5,7,13和29.
600851475143的最大质数因子是多少?
这里可以肯定的是:1.数字很大,绝对不能暴力。2.如果这是一到OJ题,那么我们的目的就是尽量缩小这个数,减少计算量。
我们都知道,任何一个合数都是可以由他的所有质因素相乘得到的,比如15=3*3*3*3*3,12=2*2*3,60=2*2*3*5.(这些数都是我随便想的),好的,我们先看一个比较小的数60,现在我们要找它的最大质因子,我们可以从最小的奇数开始枚举(当然要先枚举2这个特殊的质数,除此之外的偶数可能是质数吗?),如果可以整除说明这个奇数是其因子之一,然后判断这个奇数如果是质数,那么它就是其中一个质因子。然后原数就可以除这个因子了,为了排除已经找到的因子,我们一直将它除这个数,直到不能整除,60/=2得30,30/=2得15,到此结束此因子,我们就找到了2这个质因子;同理,到3的时候15/=3得5,找到了3这个质因子;5/5=1,可以结束,5就是我们要找的最大质因子啦。如果是多测试的话一直频繁判断素数是不是有点不爽?所以我们可以打个素数表- -。还有一个优化就是这个素数不会超过sqrt(n),可以减少循环次数,至于证明自己搜吧。
附上我的AC代码:
#include<stdio.h> #include<map> #include<math.h> using namespace std; #define ll long long #define MAX 600851475143 map<ll,bool> is; map<ll,ll> pr; void init() { ll t=(ll)sqrt(10000000),i,j,p=0; for(i=2 ; i<= t ;i++) is[i]=true; for(int i=2 ; i<=t ; i++) { if(is[i]==true) { pr[p]=i; p++; for(j=2*i ; j<=t ; j+=i) is[j]=false; } } } ll sove() { ll m=(ll)sqrt(MAX); ll num=MAX; ll ans,la,i,f; if((num&1)==0) { la=2; num>>=1; while((num&1)==0) num>>=1; } else la=1; f=3; for(i=1 ; num>1 &&f<m;i++) { f = pr[i]; if(num%f==0) { num/=f; la=f; while(num%f==0) num/=f; m=(ll)sqrt(num); } } if(num==1) return la; else return num; } int main() { init(); printf("%lld\n",sove()); }
谨防出错附上大神AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; const int MAXN = 100000000; int prime[MAXN],cnt_prime=0; bool isprime[MAXN]; void GetPrime(int MAX) { memset(isprime,0,sizeof(isprime)); int m=(int)sqrt((double)MAX); for(int i=2;i<=m;i++) { if(!isprime[i]) { for(int j=i*i;j<=MAX;j+=i) { isprime[j]=1; } } } cnt_prime=0; for(int i=2;i<=MAX;i++) { if(!isprime[i]) { prime[cnt_prime++]=i; } } } int findit(ull num) { ull m = (int)sqrt(double(num)); ull lastf,f; if((num&1)==0) { lastf = 2; num>>=1; while((num&1)==0) num>>=1; } else lastf = 1; f=3; for(int i = 2; num > 1 && f < m; i++) { f = prime[i]; if(num % f == 0) { num /= f; lastf = f; while(num%f==0) num/=f; m=(int)sqrt(double(num)); } } if(num==1) return lastf; else return num; } int main() { GetPrime(10000000); cout<<findit(600851475143)<<endl; }