用筛法求素数
C语言数组编程题及解答

C语言数组编程题及解答【程序1】用筛选法求100之内的素数筛选法又称筛法,是求不超过自然数N(N>1)的所有质数的一种方法。
据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274~194年)发明的,又称埃拉托斯特尼筛子。
具体做法是:先把N个自然数按次序排列起来。
1不是质数,也不是合数,要划去。
第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。
2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。
3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。
这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。
因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛”,简称“筛法”。
#include <stdio.h>#include <math.h>void main(){int i,j;int a[100];for(i=0;i<100;i++)a[i]=i+1;for(i=1;i<100;i++){if(a[i]==0)continue;for(j=i+1;j<100;j++)if(a[j]%a[i]==0)a[j]=0;}for(j=1;j<100;j++) //j从1开始,去除a[0](其值为1),因为1既不是质数,也不是合数if(a[j]!=0)printf("%d,",a[j]);printf("\n");}【程序2】题目:一个数如果恰好等于它的因子之和,这个数就称为“完数”。
例如6=1+2+3.编程找出1000以内的所有完数。
程序源代码:#include <stdio.h>int main(){int k[10];int i,j,n,s;for(j=2;j<1000;j++){n=-1;s=j;for(i=1;i<j;i++){if ((j%i)==0){n++;s=s-i;k[n]=i;}}if(s==0) //说明是完数{printf("%d is a wanshu:",j);for(i=0;i<=n;i++)printf("%d ",k[i]);printf("\n");}}return 1;}【程序3】题目:用选择法对10个数进行从大到小排序1.程序分析:可以利用选择法,即从后9个比较过程中,选择一个最小的与第一个元素交换,下次类推,即用第二个元素与后8个进行比较,并进行交换。
欧拉函数求法与欧拉筛法求素数

欧拉函数求法与欧拉筛法求素数欧拉函数:欧拉函数定义:对于正整数n,欧拉函数Euler(n)是1到n-1中与n互质的数的个数,特别的,Euler(1) = 1,若n为质数则有 Euler(n) = n - 1欧拉函数的两种求法:1.由定义和常识可以知道对于任意⼀个素数n有 Euler(n) = n - 1,对于m = n ^ k,Euler(m)是⾮常好求解的,显然,只有n的倍数才是不满⾜欧拉函数的定义的数,只要减去即可。
得:Euler(m) = n ^ k - n ^ (k - 1)。
另外,附加介绍以⼀点关于简化剩余系的概念,取定m > 0,若r mod m 中的每个数都与m互素,则称r mod m是与m互素的剩余类。
从所有与模m互素的剩余类中各取⼀数所组成的⼀组数称为简化剩余系。
如 m = 5 有 1 mod 5, 2 mod 5, 3 mod 5, 4 mod 5,是与m互素的剩余类。
易知模m的⼀个简化剩余系中⼀共有Euler(m)个数,有定理:设(m1, m2) = 1,若x1,x2分别通过模m1,m2的⼀个简化剩余系,则m1x2 + m2x1通过m1m2的⼀个简化剩余系。
通过这个定理我们可以得到Euler(m * n) = Euler(m) * Euler(n)。
对于任意⼀个数,可以进⾏整数分解,分解成为 m = n1 ^ x1 * n2 ^ x2 * ni ^ xi,这样根据上⾯的两个结论我们可以得到Euler(m) = Euler(n1 ^ x1) * ... * Euler(ni ^ xi) = ((n1 ^ x1) - (n1 ^ (x1 - 1))) * ... * ((ni ^ xi) - ni ^ (xi - 1)) = (n1 - 1) * (n1 ^ (x1 - 1)) * ... * (ni - 1) * (ni ^ (xi - 1)),根据这个式⼦我们可以推出如下的性质:设n为m的质因数则有(m % n == 0) (1)若 (m / n) % n != 0 有E(m) = E(m / n) * (n - 1),这⾥就是前⾯式⼦中每个质因数的前⾯的(ni - 1)。
用筛法求出100以内的全部素数

例6、用筛法求出100以内的全部素数,并按每行五个数显示。
【问题分析】⑴把2到100的自然数放入a[2]到a[100]中(所放入的数与下标号相同);⑵在数组元素中,以下标为序,按顺序找到未曾找过的最小素数minp,和它的位置p(即下标号);⑶从p+1开始,把凡是能被minp整除的各元素值从a数组中划去(筛掉),也就是给该元素值置0;⑷让p=p+1,重复执行第②、③步骤,直到minp>Trunc(sqrt(N)) 为止;⑸打印输出a数组中留下来、未被筛掉的各元素值,并按每行五个数显示。
用筛法求素数的过程示意如下(图中用下划线作删去标志):① 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {置数}② 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {筛去被2整除的数}③ 2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {筛去被3整除的数}……2 3 4 5 6 7 8 9 10 11 12 13 14 15…98 99 100 {筛去被整除的数}Program Exam53;const N=100;type xx=1 .. N; {自定义子界类型xx(类型名)}Var a: array[xx] of boolean; i,j: integer;BeginFillchar(a,sizeof(a),true);a[1] := False;for i:=2 to Trunc(sqrt(N)) doif a[I] thenfor j := 2 to N div I doa[I*j]:= False;t:=0;for i:=2 to N doif a[i] thenBeginwrite(a[ i ]:5); inc(t);if t mod 5=0 then writelnend;End.【例3】输入十个正整数,把这十个数按由大到小的顺序排列(将数据按一定顺序排列称为排序,排序的算法有很多,其中选择排序中的“简单选择排序”是一种较简单的方法)分析:要把十个数按从大到小顺序排列,则排完后,第一个数最大,第二个数次大,……;因此,我们第一步可将第一个数与其后的各个数依次比较,若发现,比它大的,则与之交换,比较结束后,则第一个数已是最大的数。
python求素数的20种算法

python求素数的20种算法20种求素数的算法1. 质数判断法:对于给定的整数n,从2到n-1依次判断n是否能被这些数整除,若都不能整除,则n为质数。
该算法的时间复杂度为O(n)。
2. 埃拉托斯特尼筛法:该算法的基本思想是从2开始,将2的倍数标记为合数,然后再找到下一个未标记的数,将其倍数标记为合数,依此类推,直到找到所有的质数。
时间复杂度为O(nloglogn)。
3. 素数定理:根据素数定理,对于给定的整数n,素数的个数约为n/ln(n),可以利用这个定理来估算给定范围内的素数个数。
4. 费马素性检验:对于给定的整数n,取一个随机整数a,如果a 的n次方模n等于a,则n可能是素数,否则一定是合数。
该算法的时间复杂度较低,但存在一定的错误概率。
5. 米勒-拉宾素性检验:该算法是费马素性检验的改进算法,通过多次的随机取数进行检验,提高了精确度。
6. 素数分解法:将给定的整数n进行素因数分解,如果分解得到的因子只有1和n本身,则n为质数。
7. Rabin-Miller素性检验:该算法是米勒-拉宾素性检验的改进算法,通过多次的随机取数进行检验,提高了精确度。
8. 欧拉素数检验:根据欧拉定理,如果对于给定的整数n,a的n-1次方模n等于1,则n可能是素数,否则一定是合数。
9. 线性筛法:该算法是埃拉托斯特尼筛法的改进算法,通过线性的方式进行筛选,可以在O(n)的时间复杂度内求解素数。
10. 素数生成器:通过不断地生成大于当前最大素数的数,并判断是否为质数,来生成素数序列。
11. 素数位数统计法:对于给定的整数n,统计从1到n中每个数的位数,然后判断每个位数的数是否为质数。
12. 素数平方和方法:对于给定的整数n,判断是否存在两个质数,使得它们的平方和等于n。
13. 素数和差法:对于给定的整数n,判断是否存在两个质数,使得它们的和或差等于n。
14. 质数的二进制表示法:对于给定的整数n,将n转换为二进制表示,然后判断二进制中是否只包含一个1,若是则n为质数。
素数常见的算法

求素数的三种方法
素数的定义:
素数也叫质数。
一个大于1的自然数,除了1和它本身之外,不能被其它自然数整除的数叫做素数;能被其它自然数整除的数叫做合数。
规定,1既不是质数也不是合数。
法一:试除法(判断素数)
让N被2如果N能被其中任何一个整数整除,则提前结束循环,N不是素数;如果N不能被其中任何一个整数整除,则N是素数。
代码实现:
法二:埃氏筛法(求一个范围中所有素数)
试除法可以用来判断一个数是否为素数,如果用来求某一范围内所有素数的话,效率就比较低。
埃氏筛法是用来解决这类问题的古老而简单高效的方法,可以快速找到[2,]n中的所有素数。
具体操作是这样的:从2开始寻找素数,每次找到一个素数后就将它的倍数全部筛掉,并将该素数存储到另一个数组中,不断循环,直到原数组为空。
法三:欧拉筛法(埃氏筛法的优化版)
埃氏筛法中,由于一个数可以既是一个素数的倍数,又是另一个素数的倍数,可以发现这会出现重复标记的情况,即同一个数被筛掉了不止一次,浪费操作了。
欧拉筛法就是在埃氏筛法的基础上多了判断的步骤,从而消失了这种重复标记的情况,核心思想是用合数中的一个因数筛掉这个合数。
具体操作为:利用已经求得的素数,第一重循环将区间内的数从小到大遍历,第二重循环将以求得的素数从小到大遍历,将这个数和素数的乘积标记为合数。
如果一个数能被素数整除,跳出循环。
埃氏筛原理

埃氏筛原理
埃氏筛原理是一种用于筛选素数的方法,又称为“埃拉托斯特尼筛法”。
它的基本思想是从2开始,将每个素数的倍数都标记为合数,直到遍历完所有小于给定数的自然数。
这个方法的效率较高,适用于求解大范围内的素数。
在使用埃氏筛原理之前,我们首先需要明确什么是素数。
素数是指只能被1和自身整除的自然数,例如2、3、5、7等。
而合数则是除了1和自身之外还能被其他数整除的自然数,例如4、6、8、9等。
埃氏筛原理的具体步骤如下:
1. 创建一个长度为n+1的布尔数组,用来标记每个数是否是素数,初始时都设置为true。
2. 从2开始遍历到n,如果当前数是素数,则将其所有的倍数都标记为合数,即将其倍数的位置在布尔数组中置为false。
3. 遍历完所有小于n的数后,布尔数组中为true的位置即为素数。
通过这个方法,我们可以快速筛选出小于给定数n的所有素数,从而进行后续的计算或分析。
需要注意的是,埃氏筛原理只能用于求解小范围内的素数,对于较大范围的素数筛选,需要使用更加高效的算法,如欧拉筛法或线性筛法。
埃氏筛原理是一种简单而高效的求解素数的方法,通过不断筛选合数,最终得到素数的集合。
它的应用范围广泛,可以用于解决各种与素数相关的问题。
对于数学爱好者和算法研究者来说,了解和掌握埃氏筛原理是一项有益的知识。
计算所有素数的公式是什么

计算所有素数的公式是什么
我们要找出计算所有素数的公式。
首先,我们需要了解什么是素数。
素数是一个大于1的自然数,且只能被1和它自身整除的数。
例如:2, 3, 5, 7, 11等都是素数。
为了找出所有素数,我们可以使用一个简单的筛选法,也称为埃拉托斯特尼筛法。
这个方法的基本思想是从2开始,逐步筛选出所有的素数。
具体步骤如下:
1.初始化一个列表,包含从2开始的所有整数。
2.从列表的第二个元素开始(索引为1的元素),假设它是一个素数。
3.将这个素数的所有倍数从列表中移除。
4.重复步骤2和3,直到列表中没有更多的元素。
5.剩下的元素就是所有的素数。
计算结果为:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
所以,1到100之间的所有素数为:[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]。
线性筛法求素数的原理与实现

何为线性筛法,顾名思义,就是在线性时间内(也就是O(n))用筛选的方法把素数找出来的一种算法,没用过线性筛素数法的人可能会奇怪,用遍历取余判定素数不是也是线性时间的吗,没错,但是确切的说线性筛法并不是判定素数的,而是在线性时间内求出一个素数表,需要判定是否是素数的时候只要看该数是否在表内就可以瞬间知道是不是素数。
比如想求10000以内的素数,定义表int a[10000],进行线性筛选后,a[n]的值就代表n是不是素数,a[n]如果是1,就代表n是素数,a[n]如果是0,就代表n不是素数,这就是查表。
再判定其他的素数也是一样,不用再做任何计算。
而如果用遍历取余,那么每判定一个数都要从头开始再遍历一遍,而线性筛法只在开始一次性运算完,以后只要查表即可,查表通常只需要1条语句。
所以如果你的程序从始至终只需要判定那么几次素数那么用遍历取余即可,但是如果需要多次判定素数,而且这个数还不是很小的话,那么线性筛法就会体现出巨大的优越性来。
线性筛法的核心原理就是一句话:每个合数必有一个最大因子(不包括它本身),用这个因子把合数筛掉,还有另一种说法(每个合数必有一个最小素因子,用这个因子筛掉合数,其实都一样,但是我觉得这种方法不太容易说明,这种方法我会在最后给出简略说明)。
这个很容易证明:这个小学就知道合数一定有因子,既然是几个数,就一定有最大的一个。
最大因子是唯一的,所以合数只会被它自己唯一的因子筛掉一次,把所有合数筛掉后剩下的就全是素数了。
先假设一个数i,一个合数t,i是t最大的因数,t显然可能并不唯一(例如30和45的最大因数都是15)。
那么如何通过i知道t呢,t必然等于i乘以一个比i小的素数。
先来说这个数为什么一定要比i小,这很显然,如果是i乘上一个比它大的素数,那么i显然不能是t最大的因子。
再来说为什么要是素数,因为如果乘上一个合数,我们知道合数一定可以被分解成几个素数相乘的结果,如果乘上的这个合数x=p1*p2*……,那么t = i * x = i * p1 * p2……很显然p1* i也是一个因数,而且大于i。
ACM 筛素数总结

【总结】关于求素数的说【两种筛法】(学习小结,请无视)素数大家都很熟了,不多说了,这里只想说一下求素数。
当然先是唯一素因子分解定理:合数a仅能以一种方式,写成如下的乘积形式:a=p1e1p2e2…prer其中pi为素数,p1<p2<…<pr,且ei为正整数对于一个整数n,当其在小于sqrt(n)范围里有一个约数,那么必然在大于sqrt(n)的范围里有对应的另一个Eratosthenes(埃拉托斯特尼筛法)都是到sqrt(n)的范围。
①。
试除法判素数对于大于1的正整数a,如果a具有小于或等于sqrt(a)的素因子,则a为合数,否则a为素数。
因此,可用区间[2,sqrt(a)]内的数去试除a,只要有一个数能整除a ,则a为合数,否则a为素数。
这种判断素复杂度O(sqrt(n)).IsPrime(a)for(i=2;i*i<=a;i++)if(a%i==0)return a为合数return a为素数②。
Sieve Of Eratosthenes(埃拉托斯特尼筛法)可以筛出2~n 范围里的所有素数。
1)将所有候选数2~n放入筛中;2)找出筛中最小数P,P一定为素数。
3)宣布P为素数,并将P的所有倍数从筛中筛去;4)重复2)至3)直到筛空.其实,当P>sqrt(n)时筛中剩下的数就已经都是素数了。
//用数组prime[MAXN]记录是否为素数;//prime[i]为0表示i为素数,否则为合数int prime[MAXN]={0};for(i=2;i*i<=n;i++){if(prime[i]==0){for(j=i+i;j<=n;j+=i)prime[j]=1;}}③。
线性筛法对于Sieve Of Eratosthenes,普通的筛法如果是一个合数,那么会被多次筛掉,比如6,当2作为素数时筛掉一线性筛法保证所有合数只被筛掉一次具体详见《ftfish利用积性函数的优化》,讲到了积性函数(对于正整数n的一个算术函数f(n),当中f(1)=1且称它为积性函数。
素数题目解答

yes
19
no
20
yes
5
1、筛法求素数
const int N=1e5+10; bool a[N]; int main(){
a[0]=a[1]=1; for(int i=2;i*i<=N;i++){
if(!a[i]){ for(int j=i*i;j<=N;j+=i) a[ j]=1;
} } scanf("%d",&n); for(int i=0;i<n;i++){
输出:
所有小于等于n的素数对。每对素数对输出一行,中间用单个空格隔开。若没
有找到任何素数对,输出empty。 样例输入 100
样例输出 35 57
11 13
17 19
29 31
41 43
59 61
71 73ຫໍສະໝຸດ 2、素数对#include<iostream> #include<cstdio> using namespace std; const int N=1e6+10; int a[N]; int main(){
3、判断素数的个数
#include<iostream> #include<cstdio> using namespace std; const int N=1e6+10; int a[N]; int main(){
int n,m,b=0; a[0]=a[1]=1; for(int i=2;i*i<=N;i++){
4、回文素数
#include<bits/stdc++.h> using namespace std; int huiwen(int i){
素数筛法算法及其原理

素数筛法算法及其原理引⾔本⽂介绍部分素数筛法的步骤以及原理,并附带 python 算法的实现本⽂介绍的筛法有:厄拉多塞筛法(Eratosthenes Sieve )Sundaram 筛法欧拉筛法(Euler Sieve )分段筛法(Segmented Sieve )增量筛(Incremental sieve )Atkin 筛法厄拉多塞筛法(Sieve of Eratosthenes )1. 厄拉多塞筛法步骤给定⼀个数 n,从 2 开始依次将 √n 以内的素数的倍数标记为合数标记完成后,剩余未被标记的数为素数(从 2 开始)算法原理如下:读取输⼊的数 n ,将 2 ⾄ n 所有整数记录在表中从 2 开始,划去表中所有 2 的倍数由⼩到⼤寻找表中下⼀个未被划去的整数,再划去表中所有该整数的倍数重复第(3)步,直到找到的整数⼤于 √n 为⽌表中所有未被划去的整数均为素数2. 厄拉多塞筛法原理⾸先,先证明这种⽅法能够标记所有 2~n 之间的合数。
由整数的唯⼀分解定理知,任意⼀个⼤于1的正整数都可以被分解成有限个素数的乘积。
因此,任意⼀个合数都可以看做是⼀个素数的倍数的形式。
对于任意⼀个合数 n ,存在 p, q ,使得 n = p·q (不妨设 p 为素数)同时可有 min(p, q) ≤ p ≤ √n ,否则会有 p · q ≥ min(p, q)2 > n ,⽭盾故可知,任意合数都能被不⼤于 √n 的素数 p 标记其次,显然,该标记⽅法并不会错误地将素数标记成合数故该⽅法能且仅能标记所有 2~n 之间的合数,所以剩下未被标记的数就是素数(从 2 开始)3. 厄拉多塞筛法代码from math import sqrtdef sieve_of_eratosthenes(n: int):is_prime = [True for _ in range(n + 1)]for i in range(2, int(sqrt(n)) + 1):if is_prime[i]:for j in range(i * i, n + 1, i):is_prime[j] = False # 筛去j# 返回从2开始未被筛去的整数return [i for i in range(2, n + 1) if is_prime[i]]在筛去素数 p 倍数的过程中,我们是从 p 2 开始,⽽不是从 2·p 开始之前厄拉多塞筛法的原理中提到过,任意合数都能被不⼤于 √n 的素数标记。
线性筛法求素数

线性筛法求素数
线性筛法是一种求素数的算法,它是埃拉托斯特尼筛法的简化版本。
其主要思想是:首先用2去筛,然后用3去筛,接下来用5去筛,依次类推,将不大于根号n的所有素数的倍数剔除,最后剩下的就是素数。
1.先把2到n之间的数字从小到大排列好,设定一个变量p等于2;
2.把2这个数字标记为素数,并把它的倍数都标记为非素数;
3.将变量p加1,如果变量p的值不大于根号n,则重复步骤2,否则将p的值作为素数;
4.重复步骤3,直到p的值大于根号n;
5.此时得到了从2到根号n之间的所有素数。
埃拉托斯特尼筛法 contan

埃拉托斯特尼筛法 contan埃拉托斯特尼筛法(Eratosthenes Sieve)是一种用于计算素数的方法,称为“素数筛”。
它是由古希腊数学家埃拉托斯特尼发现的,为了在其著作《地心学说》中计算出最大的数字,以解决困难的几何问题。
素数筛是一种非常有效的方法,可用于计算素数。
一、什么是埃拉托斯特尼筛法埃拉托斯特尼筛法是一种计算素数的方法,也叫作“素数筛”。
它是由希腊古代数学家埃拉托斯特尼发明的,用于计算出在他的著作《地心学说》中最大的数字,以解决困难的几何问题。
素数筛法采用了开普勒欧拉内外关系体系,通过删除倍数来找出素数。
二、埃拉托斯特尼筛法的步骤(1)选择一个数字N作为起始数字。
(2)将小于N的所有自然数放入一张表中(progression list),从2开始,至N为止。
(3)开始从第一个数字,也就是2开始计数,该数字是第一个素数,然后将其倍数都放入另一个表中(exclusion list),即删除这些倍数。
(4)接下来又从progression list中选择下一个最小的数字,重复2、3步骤,直到遍历完整个progression list,剩下的素数就是最终结果。
三、埃拉托斯特尼筛法的优势1. 简单有效:埃拉托斯特尼筛法采用了开普勒欧拉体系,减少了内存的消耗,因此可以快速地计算出素数。
2. 可以节省空间:只需要2个表,progression list和exclusion list,前者存放所有小于N的自然数,后者存放被排除的倍数,因此可以有效的节省计算空间。
3. 可以减少时间复杂度:素数筛法只需要遍历一次数组,而不需要计算其他数字,因此可以节省时间复杂度,更快速地计算出素数。
四、在编程中的应用素数筛法被广泛应用于不同的编程领域,如:1. 加密:素数的大数相乘可以构成公钥,而且任何人都很难破解它,因此它在加密上比较安全。
2. 随机数:埃拉托斯特尼筛法可以产生大量不重复的素数,可用于产生伪随机数。
第七章C语言谭浩强答案

7.1用筛法求100之内的素数。
解:所谓“筛法”指的是“Eratosthenes筛法”。
Eratosthenes是古希腊的著名数学家。
他采用的方法是:在一张纸上写下1~1000之间的全部整数,然后逐个判断它们是否素数,找出一个非素数就把它挖掉,最后剩下的就是素数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 2728 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 …具体做法如下:先将1挖掉(因为1不是素数)。
用2去除它后面的各个数,把能被2整除的数(如4,6,8…)挖掉,即把2的倍数挖掉。
用3去除它后面各数,把3的倍数挖掉。
分别用4,5…各数作为除数去除这些数以后的各数。
这个过程一直进行到在除数后面的数已全被挖掉为止。
例如在上表中1~50范围内的素数,要一直进行到除数为47为止。
事实上,这一过程可以简化。
如果需要找1~n数)即可。
例如对1~50,只需进行到将7上面的算法可表示为:挖去1;用刚才被挖去的数的下一个数p去除p后面的各数,把p的倍数挖掉;检查p n=1000,则检查p<31否),如果是,则返回(2)继续执行,否则就结束;纸上剩下的就是素数。
解题的基本思路有了,但要变成计算机的操作,还要作进一步的分析。
如怎样判断一个数是否已被“挖掉”,怎样找出某一个数p的倍数,怎样打印出未被挖掉的数。
可以设一个数组a,a[1]到a[100]的值分别是1,2,3,…100。
然后用上述方法将非素数“挖去”。
如果一个数被认为是非素数,就将它的值变为零,最后将不为零的数组元素输出,就是所求的素数表。
程序如下:#include <math.h>main ( ){int i,j,n,a[101];for (i=1;i<=100;i++)a[i] =i;for (i=2;i<sqrt(100);i++)for (j=i+1;j<=100;j++){if (a[i]!=0 && a[j]!=0)if (a[j]%a[i]==0)a[j]=0; } /*非素数,赋值为0,“挖掉”*/printf(“\n”);for (i=2,n=0;i<=100;i++){ if (a[i]!=0){printf(“%5d”,a[i]);n++; }if (n==10) /*此处if 语句的作用是在输出10个数后换行*/{ printf (“\n”);n=0; }}}运行结果:2 3 5 7 11 13 17 19 23 29 31 37 41 4347 53 59 61 67 71 73 79 83 89 977.2用选择法对10个整数排序(从小到大)。
筛分法的原理

筛分法的原理筛分法,又称为素数筛法或埃拉托斯特尼筛法,是一种用于筛选素数的经典算法。
它的原理是通过不断排除合数,最终得到一系列素数。
该算法的核心思想是从2开始,将所有的整数进行标记,初始状态都为合数。
然后从小到大遍历这些整数,如果当前数字是素数(即未被标记),则将其倍数都标记为合数。
在遍历完所有的数之后,剩下的未被标记的数字即为素数。
具体实现时,可以使用一个布尔数组来记录每个数字的状态,初始时都设为true。
然后从2开始,将2的倍数都标记为false,然后继续遍历为true的下一个数字,将其倍数标记为false。
一直重复这个过程,直到遍历完所有的数字。
举个例子来说明筛分法的原理。
我们以找出100以内的素数为例。
首先,我们将2标记为素数,并将2的倍数4、6、8、...都标记为合数。
然后,我们继续遍历到下一个为true的数字3,将3的倍数6、9、12、...都标记为合数。
依次类推,我们将5、7、11等素数的倍数都标记为合数。
最终,剩下的未被标记的数字即为素数。
通过筛分法,我们可以高效地找出一定范围内的素数。
该算法的时间复杂度为O(nloglogn),其中n为待筛选的范围。
相比于暴力判断每个数字是否为素数的方法,筛分法具有更高的效率。
筛分法不仅可以用于求解素数,还可以用于求解质数因子、约数个数等问题。
它在数论和密码学等领域有着重要的应用。
同时,筛分法的思想也可以启发我们解决其他问题,例如筛选特定条件的数、排除非法数据等。
总结起来,筛分法是一种高效的筛选素数的算法。
通过不断排除合数,最终得到一系列素数。
它的原理简单易懂,实现起来也相对较为简单。
在实际应用中,我们可以利用筛分法解决各种与素数相关的问题,提高算法效率。
素数的三种判断方法

素数的三种判断方法引言素数是指大于1且只能被1和自身整除的正整数。
素数在数论中扮演着重要的角色,被广泛应用于密码学、质因数分解、概率算法等领域。
因此,判断一个数是否为素数具有重要的意义。
本文将介绍三种常见的素数判断方法:试除法、埃拉托斯特尼筛法和费马素性检验。
这些方法具有不同的原理和适用范围,对于不同规模的数值可以选择适合的判断方法。
下面将逐一介绍这三种方法。
1. 试除法试除法是最简单、直观的一种素数判断方法,也是最容易理解和实现的方法。
其基本原理是:对于待判断的数n,从2开始,逐一尝试将n除以每个小于n的数d,若存在一个d能整除n,则n不是素数;若不存在,则n是素数。
以下是使用试除法判断一个数是否为素数的伪代码:Input: n (待判断的数)Output: True (是素数) 或 False (不是素数)if n <= 1:return Falsefor d in range(2, int(sqrt(n)) + 1):if n % d == 0:return Falsereturn True使用试除法进行素数判断的时间复杂度为O(sqrt(n)),空间复杂度为O(1)。
试除法对于判断较小的数值非常有效,但对于极大数值的判断则会变得非常耗时,因为需要逐一尝试除以每个可能的因子。
2. 埃拉托斯特尼筛法埃拉托斯特尼筛法(简称埃氏筛)是一种更高效的素数判断方法,适用于判断较小范围内的数是否为素数。
该方法基于一个重要的数论定理:如果p是素数,那么大于p的p的倍数一定不是素数。
以下是使用埃拉托斯特尼筛法判断一个范围内所有数的素数情况的伪代码:Input: n (待判断范围内的最大数)Output: primes (所有素数的列表)is_prime = [True] * (n+1)is_prime[0] = Falseis_prime[1] = Falsefor p in range(2, int(sqrt(n)) + 1):if is_prime[p]:for multiple in range(p*p, n+1, p):is_prime[multiple] = Falseprimes = [p for p in range(n+1) if is_prime[p]]使用埃拉托斯特尼筛法判断范围内数的素数情况的时间复杂度为O(nlog(log(n))),空间复杂度为O(n)。
线性筛法原理及素数表

线性筛法,即是筛选掉所有合数,留下质数我们知道合数可以由一个质数数与另一个数相乘得到而同时假设合数a=质数b×质数c×一个数d令e=c × d,假设b ≥ e,e为合数,令f=d × ba=f × c ,其中c即比一个合数数大的质数和该合数的乘积可用一个更大的合数和比其小的质数相乘得到这也是if(!( i % prime[j]))break;的含义,这也是线性筛法算质数表的关键所在原理:1. 任何一个合数都可以表示成一个质数和一个数的乘积2. 假设A是一个合数,且A = x * y,这里x也是一个合数,那么有:A = x * y; (假设y质数,x合数)x = a * b; (假设a是质数,且a < x)-> A = a * b * y = a * Z (Z = b * y)即一个合数(x)与一个质数(y)的乘积可以表示成一个更大的合数(Z)与一个更小的质数(a)的乘积这也是理解代码中if(i%primes[j] == 0)break;的关键例如: 如果i = 8; 那么由于i%2 == 0; 因此对于i=8就只需要检查primes[1]即可,因为对于大于primes[1]的质数,像3,有:8*3 = 2*4*3 = 12*2也就是说24(8*3=24)并不需要在8时检查,在12时才检查1#include<iostream>2using namespace std;34const int MAX=100;5bool isPrime[MAX+1];6int total;//计数7int prime[MAX+1];89//线性筛法寻找素数10void makePrime()11{12memset(isPrime,true,sizeof(isPrime));13memset(prime,0,sizeof(prime));14for(int i=2;i<=MAX;i++)15{16if(isPrime[i]) prime[total++]=i;17for(int j=0; j<total&&i*prime[j]<=MAX; j++)18{19isPrime[i*prime[j]]=false;20//i此时不是素数,只是拓展用21if(i%prime[j]==0)break; 22}23}24}2526int main()27{28makePrime();29for(int i=0;i<total;i++)30{31cout<<prime[i]<<"";32if((i+1)%10==0) cout<<endl; 33}34return0;35}。
判断素数的算法

判断素数的算法
一个正整数如果只能被1和它本身整除,那么它就是素数。
判断素数的算法有以下几种:
1.试除法:从2开始,依次判断该数能否被2、3、4、……、它本身-1整除,如果都不能整除,那么该数就是素数。
但是该算法效率不高,对于大数不太适用。
2.厄拉多塞筛法:首先将2到n的自然数列出来,然后把2的倍数筛掉(除2以外),把3的倍数筛掉(除3以外),把4的倍数筛掉(除4以外),以此类推,直到筛不出任何数为止。
剩下的所有数就都是素数了。
该算法效率较高。
3.米勒-拉宾素性检验(Miller-Rabin Primality Test):该算法借助费马小定理,通过若干次随机检验判断一个数是否为素数,其效率为O(k log^3 n),其中k 为检验次数。
该算法适用于大数的判断。
还有其他一些算法,比如Baillie-PSW素性检验、AKS测试等,但是这些算法涉及到高级数学知识,不太容易理解。
筛法求素数

具体做法是:先把N个自然数按次序排列起来。1不是质数,也不是合数,要划去。第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛”,简称“筛法”。
<1> 先将1挖掉(因为1不是素数)。
<2> 用2去除它> 用3去除它后面的各数,把3的倍数挖掉。
<4> 分别用5…各数作为除数去除这些数以后的各数。
gpy筛法

gpy筛法是一种高效的素数筛法,其原理基于欧拉筛法和线性筛法。
具体步骤如下:
1. 构造一个数组is_prime,记录每个数是否为素数。
初始时,将is_prime[1]到
is_prime[n]全部赋值为true(即都认为是素数),其中n为待求素数的范围。
2. 枚举2到n,对于每个数i,如果is_prime[i]为true,说明i是素数,则将i加入素数列表prime中,并将i的倍数(不包括i本身)全部标记为false(即不为素数)。
3. 继续枚举,重复步骤2直到枚举完n,此时prime中即为2到n之间的所有素数。
使用gpy筛法求解素数时,时间复杂度为O(nloglogn),空间复杂度为O(n)。
下面是使用Python实现gpy筛法的代码示例:
```python
def gpy_sieve(n):
is_prime = [True] * (n + 1) # 初始时全部标记为素数
prime = [] # 保存素数的列表
for i in range(2, n + 1):
if is_prime[i]:
prime.append(i)
for p in prime:
if i * p > n:
break
is_prime[i * p] = False
if i % p == 0:
break
return prime
```
以上代码中,第一个循环枚举2到n,第二个循环枚举素数列表prime中的素数,对其倍数进行标记。
如果i是p的倍数,则i*p之后的数的最小质因子为p,故在之后的遍历中不需要再次处理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
输出素数表,方法之一就是舍弃空间,换取时间,也就是用一个大数组来存放每一个数是不是素数。
这样用筛法求素,大大的减少了时间。
下面的筛法求素程序求(不输出,即不定义OUT)1亿以内的素数只需要十几秒的时间,远小于输出所需的时间。
这个程序用一个char数组来存放每一个奇数是不是素数的信息。
一个char是一个字节8位,存放8个数。
Program prime_char.cpp:
#include<iomanip>
#include<iostream>
#include<conio.h>
//#define DEBUG
#define OUT
using namespace std;
//常量定义
const long MAX=100000000;
const long CHAR_MAX=int(MAX/16+1);
const char byt[8]={128,64,32,16,8,4,2,1};
// 变量定义
/**********************************
prime saves whether n is a prime
the value of n is like:
prime[0]: 3, 5, 7, 9,11,13,15,17
prime[1]:19,21,23,25,27,29,31,33
**********************************/
unsigned char prime[CHAR_MAX];
// 函数声明
inline bool isprime(long);
inline void setcomposite(long);
void primeinitiate(void);
void out(long);
//函数定义
/****************************************
*Function main *
****************************************/
int main()
{
#ifdef DEBUG
test();
#else
long n,m;
primeinitiate();
n=5;
while(n*n<=MAX)
{
if (isprime(n))
{
#ifdef OUT
out(n);
#endif
m=int(MAX/n);
if (m%2==0) m--;
while(m>=n)
{
if (isprime(m)) setcomposite((m*n)); m-=2;
}
}
n+=2;
}
#ifdef OUT
for (;n<=MAX;n+=2)
{
if (isprime(n))
out(n);
}
#endif
#endif
cout << "OK";
getch();
return 0;
}
/****************************************
*Test function *
****************************************/ void test(void)
{
}
/****************************************
*Function primeinitiate *
*to initiate the array prime[] *
*input : nothing *
*output : nothing *
****************************************/ void primeinitiate(void)
{
long i;
for(i=0;i<CHAR_MAX;i++)
{
if (i==0) prime[i]=237; //11101101
else if(i%3==0) prime[i]=109; //01101101
else if(i%3==1) prime[i]=182; //10110110
else if(i%3==2) prime[i]=219; //11011011
}
}
/****************************************
*Function isprime *
*To know if we haven't been sure that *
* n is a composite *
*Input : n *
*Output : false if we are sure that n *
* is a composite; *
* ture if we aren't sure that n*
* is a composite; *
****************************************/
inline bool isprime(long n)
{
return ((prime[int((n-3)/16)] & byt[((n-3)%16)/2]) != 0); }
/****************************************
*Function setcomposite *
*To let us be sure that an integer is *
*a prime *
*Input : n *
*Output : nothing *
****************************************/
inline void setcomposite(long n)
{
prime[int((n-3)/16)] &= ~byt[((n-3)%16)/2];
// return UNCHECKED;
}
void out(long n)
{
static long i=0;
cout << setw(5) << setiosflags(ios::right)<< n << " ";
i++;
i%=100;
if (i%10==0) cout << endl;
if (i%100==0) getch();
}
(以上程序经过Dev-C++ 4.9.6.0编译通过)
很久以前编的程序,现在拿出来见见天日吧。