您的位置:首页 > 其它

POJ - 3048 区间数的最大质因子

2018-03-13 16:31 253 查看
To improve the organization of his farm, Farmer John labels each of his N (1 <= N <= 5,000) cows with a distinct serial number in the range 1..20,000. Unfortunately, he is unaware that the cows interpret some serial numbers as better than others. In particular, a cow whose serial number has the highest prime factor enjoys the highest social standing among all the other cows.

(Recall that a prime number is just a number that has no divisors except for 1 and itself. The number 7 is prime while the number 6, being divisible by 2 and 3, is not).

Given a set of N (1 <= N <= 5,000) serial numbers in the range 1..20,000, determine the one that has the largest prime factor.

Input

* Line 1: A single integer, N

* Lines 2..N+1: The serial numbers to be tested, one per line

Output

* Line 1: The integer with the largest prime factor. If there are more than one, output the one that appears earliest in the input file.

Sample Input

4
36
38
40
42


Sample Output

38


Hint

OUTPUT DETAILS:

19 is a prime factor of 38. No other input number has a larger prime factor.

思路1

预处理出1~20000的所有素数

对于每个n,看最后整除n的素数时是多少 即是n的最大质因子

复杂度为n∗2e4/ln(2e4)n∗2e4/ln(2e4)

代码示例1

//暴力 复杂度为n*2e4/ln(2e4)
#include<iostream>
using namespace std;

const int maxn=2e4+10;

bool valid[maxn];
int ans[maxn];
int tot;

void get_prime(int n)
{
tot=0;
for(int i=2;i<=n;++i) valid[i]=true;
for(int i=2;i<=n;++i){
if(valid[i]){
ans[++tot]=i;
}
for(int j=1;j<=tot && ans[j] * i <=n ;++j){
valid[i*ans[j]]=false;
if(i%ans[j]==0) break;
}
}
}

int main()
{
get_prime(2e4);
int t,n,Ans,res;
cin>>t;
res=2;
int sum=t;
while(t--)
{
cin>>n;
sum-=n;
for(int i=1;i<=tot && ans[i]<=n;++i){
if(n%ans[i]==0 && ans[i]>res){
Ans=n;
res=ans[i];
}
}
}
if(sum==0) cout<<1<<endl;
else cout<<Ans<<endl;
return 0;
}


思路2 优化

在埃筛中我们用质数的倍数去筛区间

所有的合数会被质因子筛去

那我们可以留下最大的这样的质因子

for(int i=2;i<=n;++i) ans[i]=i;
for(int i=2;i<=n;++i){
if(ans[i]==i){//素数
for(int j=i*2;j<=n;j+=i)
ans[j]=i;
}
}


注意这里不能提前n/i < i break 因为我们要留下最大的质因子 而不是仅仅筛去

下面j=i*2 而不是i * i 同理

时间复杂度O(nlogn)

代码示例2

 //筛法求 1~n 内数的最大质因数  O(nlogn)
#include<iostream>
using namespace std;

const int maxn=2e4+10;

int ans[maxn];//数的最大质因子 素数就是自己
int tot;

void get_prime(int n)
{
for(int i=2;i<=n;++i) ans[i]=i; for(int i=2;i<=n;++i){ if(ans[i]==i){//素数 for(int j=i*2;j<=n;j+=i) ans[j]=i; } }
}

int main()
{
get_prime(2e4);
int t,n,res,Ans;
cin>>t;
int sum=t;
res=2;
while(t--)
{
cin>>n;
sum-=n;
if(ans
>res){
res=ans
;
Ans=n;
}
}
if(sum==0) cout<<1<<endl;
else<
ec07
/span> cout<<Ans<<endl;
return 0;
}


思考

在素数背景下

遇到区间的问题

要尽量往筛法 上思考 往往可以将n2/lognn2/logn的 复杂度优化为 nlognnlogn

比如经典的埃拉托斯特尼素数筛法欧拉线性筛法

埃塞时间不敌线性筛 但是其能保留一些有效的信息

比如这里的①数的最大质因子

垃圾变宝贝了(:

埃塞还能处理②大区间的素数筛

http://blog.csdn.net/feynman1999/article/details/79533130

对于欧拉素数筛

所有线性筛积性函数都必须基于线性筛素数

这两种方法都是经典的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: