用筛法求素数
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。
- 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编译通过)
很久以前编的程序,现在拿出来见见天日吧。