您的位置:首页 > 其它

素数筛选

2015-05-22 09:02 162 查看
关于素数筛选,ACM中常用的有两种方法:埃拉托色尼(Eratosthenes)筛法( 复杂度为O( nloglogn ) )和快速筛选法(也叫线性筛法,复杂度为O(n))。

先说第一种筛法:

//埃拉托色尼(Eratosthenes)筛选法:
#define N 10000
bool prime
; //纪录N以内的素数
int  p
; //p[i]是第i个素数
int  k=0; //纪录素数的个数
void isprime()   
{
long long i,j;
memset(prime,true,sizeof(prime));
for(i=2; i<N; i++)
{
if(prime[i])
{
p[k++]=i;
for(j=i*i; j<N; j+=i)
prime[j]=false;  
}
}   
}


这种筛法在n为10^6甚至更大的时候可以快速求出1到n之间的所有素数,把之前找出的素数的倍数标记为合数,没被标记的自然为素数,时间复杂度为O(nloglogn),这种方法在解决一般的素数问题中足以。

但不得不说另一种时间复杂度为O(n)的快速筛选法:

//线性筛法:
bool isPrime
;
int prime
;
int total;
void makePrime()
{
memset(isPrime,true,sizeof(isPrime));
memset(prime,0,sizeof(prime));
for(int i=2; i<=N; i++)   
{
if(isPrime[i]) prime[total++]=i;
for(int j=0; j<total && i*prime[j]<=N; j++)
{
isPrime[i*prime[j]]=false;
if(i%prime[j]==0) break;   
}   
}   
}


它与埃拉托色尼筛法类似,但它保证使任何一个合数,只被它的最小质因数标记过一次,所以整个算法是线性的。但就实际问题而言,两者在运算速度上没有太大差别,大家可大致了解一下。

下面我们来看一下 HDU2710:筛选出1到n之间的所有数的最大最大质因数:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2710

实现代码如下:

#include <cstdio>
#include <iostream>
using namespace std;
const int maxn=20005;
int max_factor[maxn]= {0,1};
void init()
{
for(int i=2; i<=maxn; i++)
{
if(!max_factor[i])
for(int j=i; j<=maxn; j+=i)
max_factor[j]=i;
}
}
int main()
{
init();
int n,num,ans;
while(scanf("%d",&n)!=-1)
{
int ans_f=0;
for(int i=0; i<n; i++)
{
scanf("%d",&num);
if(ans_f<max_factor[num])
{
ans_f=max_factor[num];
ans=num;
}
}
printf("%d\n",ans);
//printf("ans_f=%d\n",ans_f);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: