筛法求素数
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的素数的算法。
该算法是著名古希腊数学家埃拉托斯特尼提出的,是现今仍用于素数的概念的基础。
1)首先,应该创建一个长度为n的bool型数组,该数组包含每一个数字的状态。
这里,用0表示素数,1表示非素数。
2)从2开始,遍历每个数字,判断其是否为素数,如果是素数,则标记其所有倍数的状态都为非素数,即将其倍数的状态由0变为1,例如将4、6、8、10状态改为非素数状态。
3)当已遍历完所有数字之后,状态为0的数就都是素数了。
这一算法具有时间复杂度O(n),空间复杂度O(n),是相对理想的素数算法。
在实际应用中,有另一种改进算法叫‘筛素数算法’,在此基础上加入了一步优化,使得算法的时间复杂度从O(n)降低到O(nloglogn)。
大素数筛法 -回复

大素数筛法-回复大素数筛法(也称为厄拉多塞筛法)是一种用于筛选素数的高效算法。
它使用了一种简单而有趣的方法,通过筛除非素数的倍数来逐渐找出所有的素数。
在这篇文章中,我们将一步一步地讲解大素数筛法的原理和实现过程。
首先,让我们来回顾一下什么是素数。
素数是指只能被1和它本身整除的数,例如2、3、5、7等。
素数在数论和密码学等领域具有重要的应用,因此求素数一直是数学家和计算机科学家们感兴趣的问题。
大素数筛法的基本思想是从2开始,将所有倍数都标记为非素数,然后继续找到下一个未被标记的数,重复这个过程,直到筛选完成。
下面我们将一步一步地演示这个算法:1. 首先,我们需要确定一个上限N,以确定需要筛选的素数范围。
我们将从2到N的所有数都视为候选数。
2. 创建一个布尔数组isPrime,其长度为N+1。
开始时,将数组中的所有元素都设置为true,表示它们都是素数的候选者。
3. 从2开始,将所有2的倍数(除了2本身)标记为非素数。
然后,再找到下一个未被标记的数,即3,将所有3的倍数(除了3本身)标记为非素数。
4. 接下来,找到下一个未被标记的数,即5,将所有5的倍数(除了5本身)标记为非素数。
我们继续这个过程,直到筛选到√N为止。
5. 最后,遍历isPrime数组,将所有仍然标记为true的数添加到一个结果数组中,这些数就是素数。
现在,我们来使用一个具体的例子来说明大素数筛法的执行过程。
假设我们想要找出小于或等于30的所有素数。
首先,我们将确定上限N为30,并创建一个长度为31的布尔数组isPrime。
接下来,我们将从2开始,将所有2的倍数(除了2本身)标记为非素数。
在isPrime数组中,我们将2的倍数6、10、14、18、22、26和30都设置为false。
继续寻找下一个未被标记的数,即3。
将所有3的倍数(除了3本身)标记为非素数。
在isPrime数组中,我们将3的倍数9、15、21、27都设置为false。
第十一讲 初等数论-2

12
• 分析: 分析:
–先明确下各个变量代表的意思: 先明确下各个变量代表的意思: 先明确下各个变量代表的意思
• x:青蛙A的出发点坐标 青蛙A • y:青蛙B的出发点坐标 青蛙B • m:青蛙A一次能跳m米 青蛙A一次能跳m • n:青蛙B一次能跳n米 青蛙B一次能跳n • L:纬度线总长L米 纬度线总长L
2
gcd(最大公因子) 最大公约数 gcd(最大公因子)
• Euclidean算法求两个正整数a和b的 Euclidean算法求两个正整数a 算法求两个正整数 gcd。先令r gcd。先令r0为a,r1为b,接着执行如 下运算: 下运算:
3
最大公约数
• GCD递归定理:对任意非负整数a和任意 GCD递归定理 对任意非负整数a 递归定理: 正整数b 正整数b,gcd(a, b) = gcd(b, a mod b)。 b)。
7
扩展欧几里德算法
程序代码如下: 程序代码如下: int extended_ gcd(int a, int &y){ int t, gcd; if (b == 0) { x = 1; y = 0; return a; } gcd = extended_ gcd t = x; x = y; y = t return gcd; } int b, int &x,
14
第三章
同 余
同余是数论中的重要概念, 同余是数论中的重要概念,同余理论是研究整数 问题的重要工作之一.本章介绍同余的基本概念, 问题的重要工作类和完全剩余系.
15
例3. 求 7 的个位数.
7 解:1 ≡ −3(mod10), 7 2 ≡ −1(mod10), 7 4 ≡ 1(mod10)
埃氏筛质数

埃氏筛质数埃氏筛法也称作埃拉托色尼筛法,是一种数学方法,用于计算素数。
这种方法最初由古希腊数学家埃拉托色尼发明,现在被广泛应用于计算机科学和数学中。
它的核心思想是通过排除不是素数的数字,来确定素数的集合。
这个方法非常简单直观,但对于大数和高效的实现方法需要一定的技巧和优化。
埃氏筛法的实现方式是从2开始,逐一遍历所有的数字,并标记其所有的倍数为非素数,也就是合数。
当所有的数字都被遍历完成后,代表没有被标记的所有数字都是素数。
这种方法的核心代码如下:```def sieve_of_eratosthenes(n):primes = [True] * nprimes[0] = primes[1] = Falsefor i in range(2, int(n ** 0.5) + 1):if primes[i]:for j in range(i * i, n, i):primes[j] = Falsereturn [i for i in range(n) if primes[i]]```在这个代码中,我们首先初始化一个大小为n的质数列表,并将所有的值都初始化为True。
接着,我们将0和1标记为非素数。
然后从2开始,遍历所有小于n的数字,当我们遇到一个素数时,我们就将其所有的倍数都标记为非素数。
在这个遍历的过程中,我们可以使用一个优化技巧,也就是只标记比当前数大,其倍数之前没有被标记过的数字。
这个优化可以大大减少不必要的计算,提高程序的运行效率。
另外,我们在循环遍历中,也可以将遍历的结束条件限制在小于根号n,这是因为如果遍历到大于根号n的数时,其倍数一定已经在之前被标记过了。
在完成标记过程后,我们只需要遍历所有的数字,将未被标记的数字加入到素数集合中即可。
这个算法的时间复杂度是O(nloglogn),空间复杂度是O(n),虽然有许多优化筛法可以进一步的降低时间复杂度,但在实践中,埃氏筛法已经足够快和简单了,除非需要处理非常大的素数集合,否则不需要使用更高级的算法。
用筛法求出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】输入十个正整数,把这十个数按由大到小的顺序排列(将数据按一定顺序排列称为排序,排序的算法有很多,其中选择排序中的“简单选择排序”是一种较简单的方法)分析:要把十个数按从大到小顺序排列,则排完后,第一个数最大,第二个数次大,……;因此,我们第一步可将第一个数与其后的各个数依次比较,若发现,比它大的,则与之交换,比较结束后,则第一个数已是最大的数。
c语言求素数最快方法

c语言求素数最快方法摘要:1.引言2.最快方法:埃拉托斯特尼筛法(Sieve of Eratosthenes)3.算法原理4.C语言实现5.代码解析6.性能测试与优化7.结论正文:**引言**在计算机科学和编程领域,寻找素数是一种常见的任务。
素数是指大于1的自然数中,除了1和它本身以外,不能被其他自然数整除的数。
求解素数问题有助于理解数论、密码学等领域。
本文将介绍求解素数的最快方法——埃拉托斯特尼筛法(Sieve of Eratosthenes)及其C语言实现。
**最快方法:埃拉托斯特尼筛法(Sieve of Eratosthenes)**埃拉托斯特尼筛法是一种基于二维数组的算法,用于找出小于等于上限的素数。
该算法利用了素数的性质:如果一个数是素数,那么它的平方模小于等于上限的数也是素数。
通过不断标记数组中的素数,最终得到小于等于上限的素数。
**算法原理**1.创建一个二维数组,用于存储小于等于上限的数。
2.初始化数组中的所有元素为1,表示都是素数。
3.从2开始,遍历数组,将数组中的所有素数两两相乘,得到的结果大于上限的,将其对应的元素标记为0,表示该数不是素数。
4.重复步骤3,直到数组中的所有元素都被标记或遍历到上限。
**C语言实现**以下是一个简单的C语言实现:```c#include <stdio.h>#include <stdbool.h>void sieve_of_eratosthenes(int limit) {bool *prime = (bool *)malloc((limit + 1) * sizeof(bool));for (int i = 0; i <= limit; i++) {prime[i] = true;}for (int p = 2; p * p <= limit; p++) {if (prime[p]) {for (int i = p * p; i <= limit; i += p) {prime[i] = false;}}}for (int i = 2; i <= limit; i++) {if (prime[i]) {printf("%d ", i);}}free(prime);}int main() {int limit;printf("请输入一个上限:");scanf("%d", &limit);sieve_of_eratosthenes(limit);return 0;}```**代码解析**1.首先,我们需要一个布尔数组来存储小于等于上限的数是否为素数。
线性筛法求素数的原理与实现

何为线性筛法,顾名思义,就是在线性时间内(也就是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。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
筛法
筛法,是求不超过自然数N(N>1)的所有质数的一种方法。
据说是古希腊的埃拉托斯特尼(Eratosthenes,约公元前274~194年)发明的,又称埃拉托斯特尼筛子。
具体做法是:先把N个自然数按次序排列起来。
1不是质数,也不是合数,要划去。
第二个数2是质数留下来,而把2后面所有能被2整除的数都划去。
2后面第一个没划去的数是3,把3留下,再把3后面所有能被3整除的数都划去。
3后面第一个没划去的数是5,把5留下,再把5后面所有能被5整除的数都划去。
这样一直做下去,就会把不超过N的全部合数都筛掉,留下的就是不超过N的全部质数。
因为希腊人是把数写在涂腊的板上,每要划去一个数,就在上面记以小点,寻求质数的工作完毕后,这许多小点就像一个筛子,所以就把埃拉托斯特尼的方法叫做“埃拉托斯特尼筛”,简称“筛法”。
(另一种解释是当时的数写在纸草上,每要划去一个数,就把这个数挖去,寻求质数的工作完毕后,这许多小洞就像一个筛子。
)
例如,用筛法找出不超过30的一切质数:
不超过30的质数2,3,5,7,11,13,17,19,23,29共10个。
使用pascal语言,利用筛法求素数的代码:
ReadLn(n);{需要求2~n之间所有的素数}
For i:=2 To n Do a := True;{全部清成真,表示目前是素数}
For i:=2 To n Do
If a Then{当该数纪录是质数时开始筛选}
For j:=1 To n Div i Do a[2 * j] := False;{筛掉所有质数的倍数}
sum := 0;{统计范围内有多少个质数}
For i:=2 To n Do
If a Then Begin{如果是质数就输出}
Write(i, ' ');
Inc(sum);
End;
WriteLn(sum);{输出总数}
readln(n);(读入N);
for i:=2 to n do a[i]:=true;(先将a数组全部定义为素数,即用true代表素数,false 合数)
for i:=2 to trunc(sqrt(n)) do(1 to n 也可以,不过比较浪费时间)
begin
if a[i]=true then (如果这个数是素数,则执行.这样比较省时间)
begin
for j:=2 to n div i do
a[i*j]=false;(将一切可以被2、3、4...整除的数全部定义为合数)
end;。