Eratosrhenes筛选法

1简介

埃拉托色尼选筛法(the Sieve of Eratosthenes)简称埃氏筛法,是古希腊数学家埃拉托色尼(Eratosthenes 274B.C.~194B.C.)提出的一种筛选法。 是针对自然数列中的自然数而实施的,用于求一定范围内的质数,它的容斥原理之完备性条件是p=H~。

2步骤

(1)先把1删除(现今数学界1既不是质数也不是合数)

(2)读取队列中当前最小的数2,然后把2的倍数删去

(3)读取队列中当前最小的数3,然后把3的倍数删去

(4)读取队列中当前最小的数5,然后把5的倍数删去

(5)如上所述直到需求的范围内所有的数均删除或读取

注:此处的队列并非数据结构队列,如需保留运算结果,处于存储空间的充分利用以及大量删除操作的实施,建议采用链表数据结构

该算法是用空间换时间,代码实现如下

#include <stdio.h>
#include <stdlib.h>
#define SIZE 10000
#define TRUE 1
#define FALSE 0
int
main()
{
char sieve[ SIZE ]; /* the sieve */
char *sp; /* pointer to access the sieve */
int number; /* number we’re computing */
/*
** Set the entire sieve to TRUE.
*/
for( sp = sieve; sp < &sieve[ SIZE ]; )
*sp++ = TRUE;
/*
Solution 6.4 continued . . .
Pointers on C—Instructor′s Guide 33
** Process each number from 3 to as many as the sieve holds. (Note: the
** loop is terminated from inside.)
*/
for( number = 3; ; number += 2 ){
/*
** Set the pointer to the proper element in the sieve, and stop
** the loop if we’ve gone too far.
*/
sp = &sieve[0]+(number-3) / 2;
if( sp >= &sieve[ SIZE ] )
break;
/*
** Now advance the pointer by multiples of the number and set
** each subsequent entry FALSE.
*/
while( sp += number, sp < &sieve[ SIZE ] )
*sp = FALSE;
}
/*
** Go through the entire sieve now and print the numbers corresponding
** to the locations that remain TRUE.
*/
number=2;
printf( "%8d", number );
for( number = 3, sp = &sieve[ 0 ];
sp < &sieve[ SIZE ];
number += 2, sp++ ){
if( *sp )
printf( "%8d", number );
}
return EXIT_SUCCESS;
}

 由于除了2之外,所有偶数都不是质数,所以令数组中的元素只对应奇数,可使程序的空间效率提高一倍。

n(数组下标) 0  1  2  3  4  5  6  7  8  9  10

s(奇数)     3  5  7  9   11 13   15    17    19    21    23

显然s=2*n+3    由于n增加1时,s增加2.

所以对s进行筛选时

读取3,然后将2*3=6的倍数删去(因为是对奇数进行筛选)——》对n将3k+0的数删去

所以对下标n进行筛选时,可删去3k,1+5k,2+7k。。。。。

for( number = 3; ; number += 2 ){
/*
** Set the pointer to the proper element in the sieve, and stop
** the loop if we’ve gone too far.
*/
sp = &sieve[0]+(number-3) / 2;
if( sp >= &sieve[ SIZE ] )
break;
/*
** Now advance the pointer by multiples of the number and set
** each subsequent entry FALSE.
*/
while( sp += number, sp < &sieve[ SIZE ] )
*sp = FALSE;
}

Eratosrhenes筛选法

时间: 2024-08-10 17:22:07

Eratosrhenes筛选法的相关文章

算法笔记_012:埃拉托色尼筛选法

1 问题描述 Compute the Greatest Common Divisor of Two Integers using Sieve of Eratosthenes. 翻译:使用埃拉托色尼筛选法计算两个整数的最大公约数.(PS:最大公约数也称最大公因数,指两个或多个整数共有约数中最大的一个) 2 解决方案 2.1 埃拉托色尼筛选法原理简介 引用自百度百科: 埃拉托色尼筛选法(the Sieve of Eratosthenes)简称埃氏筛法,是古希腊数学家埃拉托色尼(Eratosthene

筛选法求素数

筛选法求素数,不断的用3,5,7,等素数作为筛子,筛除这些数的倍数,即将合数筛除.用辅助数组p记录数i是否是素数. vector<int> prime(int n) { vector<int> p(n+1); for(int i=2;i<=n;i+=2) { if(i%2==0&&i>2) p[i]=0; else p[i]=1; } for(int i=3;i<=(int)(sqrt((double)n));i+=2) { if(p[i]) fo

Eratosthenes筛选法构造1-n 素数表

筛选法:对于不超过n的每个非负整数p,删除2p,3p,4p...当处理完所有数之后,还没没删除的就是素数. 代码中进行了相应的优化. 1 #include<bits/stdc++.h> 2 using namespace std; 3 int vis[10000]; 4 int main() 5 { 6 int n; 7 while(scanf("%d",&n)) 8 { 9 //-------------- 10 int m=sqrt(n+0.5); 11 mem

素数筛选法

筛选法(埃拉托色尼(Eratosthenes)筛法)求素数,例如1~100 思想:逐个筛选,直到int(sqrt(100))个 1)因为1不是质数,将1筛去 2)2是质数,将2的倍数全都挖掉 3)3是质数,将3的倍数全都挖掉 4)4已经被挖去,不进行与4相关的操作 5)5是质数,将5的倍数全都挖掉 6)这个过程一直进行到后面的数全都挖掉为止 不是从1开始:如10~18----一个一个筛--->18 #include <stdio.h> #include <math.h> #i

hdu 5407 CRB and Candies(素数筛选法,除法取模(乘法逆元))

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5407 解题思路: 官方题解: The problem is just to calculate g(N) =\ LCM(C(N,0), C(N,1), ..., C(N, N))g(N) = LCM(C(N,0),C(N,1),...,C(N,N)). Introducing function f(n) =\ LCM(1, 2, ..., n)f(n) = LCM(1,2,...,n), the

HDU 1406.完数【筛选法以及特殊方法】【7月27】

完数 看来我的心还是不够细啊,这对一个ACMer来说,太致命了! Problem Description 完数的定义:如果一个大于1的正整数的所有因子之和等于它的本身,则称这个数是完数,比如6,28都是完数:6=1+2+3:28=1+2+4+7+14. 本题的任务是判断两个正整数之间完数的个数. Input 输入数据包含多行,第一行是一个正整数n,表示测试实例的个数,然后就是n个测试实例,每个实例占一行,由两个正整数num1和num2组成,(1<num1,num2<10000) . Outpu

数组拷贝、数组函数、通过数组函数来模拟数据结构的栈和队列、回调的意义、数组函数的排序问题、算法以及寻找素数的筛选法

1.数组的拷贝数组拷贝时指针的指向问题. 数组在拷贝时,指针的位置随之复制[这一点拷贝是完全一样]但是如果拷贝的数组的指针是非法的,那么拷贝出新指针的位置进行初始化<?php$arr1=array('123');end($arr1);next($arr1);//这个指针非法$arr2 = $arr1;//这里进行数组的拷贝var_dump(current($arr2));//得到指向‘123’元素的指针var_dump(current($arr1));//此时这个数组的指针有问题?> 但是拷贝

HDU 2161 Primes (素数筛选法)

题意:输入一个数判断是不是素数,并规定2不是素数. 析:一看就很简单吧,用素数筛选法,注意的是结束条件是n<0,一开始被坑了... 不说了,直接上代码: #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; typedef long long LL; const int maxn = 16000 + 10; int p

关于素数的快速查找——素数筛选法

利用素数筛选法进行素数的快速查找.原理很简单,素数一定是奇数,素数的倍数一定不是素数.思路如下: 预定义N表示10000,即表示查找10000以内的素数,首先定义数组prime[]对N以内的数进行标记,奇数存为1,偶数存为0,最终实现结果为素数的prime值为1,因此将prime[2]赋值为1(2是素数).之后利用for循环,对N以内的奇数进行遍历(注意for循环的条件控制),for里用if判断是否为素数(奇数),若是,执行内部嵌套的for循环判断该奇数是否为素数,若是则标记为1,若不是则pri