首页 > 编程知识 正文

c语言用质数表求完美数,c语言求质数的最快方法

时间:2023-05-04 05:41:11 阅读:164190 作者:1480

什么是目录素数(素数)? 第一种方法是暴力解决第二种方法。 奇数第三种方法,奇数双管齐下第四种方法,巧排第五种方法,巧平方根表示法1 :表示法2 :质数是什么?

素数也称为素数。 是大于1的自然数,除了1和本身以外,不能被其他自然数整除的数称为素数。 (1既不是素数,也不是合数。 ———来自百度百科

第一种方法是,在暴力解决中,将一个数设为x,根据素数的定义来判断x是否为素数。 看看能不能被2、3、4、4、x-1整除。 如果不能被任何整数整除,则其数量为素数。

例如,要判断11是否为素数,请看看能否被以下10的数整除。

2、3、4、5、6、7、8、9、10

11不能被任意一个数整除,所以判断为素数。

如果你要找1—1000的素数,你可以控制自己把x从2增加到1000。 然后,x每从1增加一次,就从2开始寻找能被x整除的数,直到找不到结尾为止。 因此,可以用两层for循环控制,在第一层产生x为21000的数字,在第二层for循环产生2到x-1的数,判断是否能被整除。 (1不是素数,所以排除1 )

此外,设置了计数器count来计数估算次数,便于与以下方法进行比较。 代码如下所示。

1--1000内的素数(素数) #include stdio.hint main ) ) {int x=0; int i=0; unsigned int count=0; //统计运算的次数for(x=2; x 1000; 在x(//2到1000之间寻找素数(for ) I=2; i x; 尝试I//除法,看看能否被x整除,x{count; 找到可以被if(x%I==0)//x整除的数({break; }找出等于}if(x==I )//x但不能被整除的,证明是素数(printf ),x ); }printf((n(n(n ) n ) ); printf ('运算次数: %d ',count ); 返回0; }第一种方法的执行结果:

第二种方法是奇数,第一种方法有点复杂吗? 当然。

事实上,从质数开始:

在2、3、5、7、9、11、13、17、19中发现了什么规律吗?

慢着,那就是2以外的2的倍数(4、6、8、10、12、14、18)不是素数。

所以,我们第一层的for循环不是一步一步地增加1,而是从3增加2不是也可以吗? 从而产生3、5、7、9、11从而可以巧妙地避免偶数。 代码如下所示。

# define _ CRT _ secure _ no _ warnings1# include stdio.hint main ({ intx=0; int i=0; unsigned int count=0; x=2; printf('%d ',x ); //因为已经知道2是素数,所以首先首先打印for (x=3; x 1000; 增加x=2(/3到2 ) for )的I=2; i x; I ) {count; if(x%I==0) {break; }if(x==I ) printf ) ' %d ',x ); }printf((n(n(n ) n ) ); printf ('运算次数: %d ',count ); 返回0; }使用第二种方法运行结果:

第一个和第二个比较图像:

第二个似乎并不比第一个运算少很多,但我发现这是因为在33、66、666这个最初阶段判断i=3的时候,马上就可以判断不是素数,所以运算次数没有减少很多。

第三种方法是用奇数双管结合第二种方法,除了2以外是它们的2的倍数(4、6、8、10、12、14、18 ) ) ) ) )不是素数)。

所以2以外的素数一定是奇数。

因此,在判断11是否为素数时,不需要判断是否能被2、3、4、5、6、7、8、9、10这九个数整除,只要判断是否能被3、5、7、9整除就可以了。

因此,可以将第二层的for循环控制为从3到2增加,而不是从1开始增加。

代码如下所示。

# define _ CRT _ secure _ no _ warnings1# include stdio.hint main ({ intx=0; int i=0; unsigned int count=0; x=2; printf('%d ',x ); for(x=3; x 1000; 只发生x=2(//奇数) for ) I=3; i x; i =2)//只产生奇数{count; if(x%I==0) {break; }if(x==I ) printf ) ' %d ',x ); }printf((n(n(n ) n ) ); printf ('运算次数: %d ',count ); 返回0; }用第三种方法执行结果:

第四种方法是成功地使用数组,根据第三种来看,可以发现以下内容

下规律:
不能被3整除的整数也无法被大于3的那些3的倍数(6、9、12······)整除。
不能被5整除的整数也无法被大于5的那些倍数(10、15、20······)整除。
所以,如果整数x无法被小于x的质数整除,那么x就是质数。
根据这个条件,我们求质数就有了另外一条思路:我们用数组来保存质数,控制x自增后,用x除去数组的每一个元素,如果不能整除则是质数,并且保存到数组中。

因此,我们先把2、3这两个质数保存到数组中,第一层for循环依旧是控制x自增,第二层for循环来遍历数组。遍历后如果都不能整除,则存到数组中。如果有一个能被整除,则不是质数,不保存。

代码如下:

#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>int main(){int arr[500] = { 0 };int x = 0;int i = 0;unsigned int count = 0;int sum = 0; //定义数组的下标arr[sum] = 2; //把2存到数组中sum++;arr[sum] = 3; //把3存到数组中sum++;for (x = 5; x < 1000; x += 2){ //从下标0开始遍历,直到数组的最后一个质数for (i = 0; i < sum; i++ ) {count++;if (x % arr[i] == 0){break;}}if (sum == i) //遍历后都不能整除{arr[sum] = x; //把质数保存到数组中sum++; //下标加1,为下次放做准备}}for (i = 0; i < sum; i++){printf("%d ", arr[i]);}printf("nnn");printf("运算的次数:%d ", count);return 0;}

运算结果:

第五种方法,巧用平方根 写法1:

我们设两个整数a和b,如果不是质数的话,整数x就可以写成 x=a * b 比如:
36=2 * 18
36=3 * 12
36=4 * 9
36=6 * 6
如果整数x为质数,那么就不可能写成 x = a * b的形式。所以如果整数x无法被小于等于x的平方根的质数整除,则x为质数。
因此,我们可以在第四种方法上改造一下,就是在第二层for循环,从数组的第一个元素出发,每一个都写成平方,直到平方大于整数x退出循环。
代码如下:

//第五种方法,巧用平方根,写法1:#include <stdio.h>int main(){int arr[500] = { 0 };int x = 0; //定义要找质数的变量int i = 0;unsigned int count = 0;int sum = 0; //定义数组下标arr[sum] = 2; //2是质数,储放到数组中sum++;arr[sum] = 3; //3也是质数,放到数组中sum++;for (x = 5; x < 1000; x += 2) //只查找奇数{for (i = 0;arr[i] * arr[i] <= x; i++) //利用数组中的元素平方去排查{count++;if (x % arr[i] == 0) //不是质数{break;}}if (arr[i]*arr[i]>x) //为质数{arr[sum] = x; //把找到的奇数放到数组中sum++; //下标加1}}for (i = 0; i < sum; i++){printf("%d ",arr[i]);}printf("nnn");printf("运算的次数:%d ", count);return 0;}

运算结果:

写法2:

我们不要数组也可以,直接在第三种方法上改造。
代码如下:

//第五种方法,巧用平方根,写法二:#include <stdio.h>int main(){int x = 0;int i = 0;unsigned int count = 0;x = 2;printf("%d ",x);for (x = 3; x <= 1000; x += 2){for (i = 2; i*i<=x; i++) //控制第二层循环{count++;if (x % i == 0){break;}}if (i*i>x){printf("%d ",x);}}printf("nnn");printf("运算的次数为:%d ",count);return 0;}

运算结果:

总结

我们从第一种的简单粗暴到最后的优良改造,运算次数一步步地减少,大家是否领悟到了编程的优美了呢?我特别推荐最后一种的写法二,既不用数组,也可以节省很多的运算时间。

如果有错误的地方,还有改进的方法,欢迎在评论区指出。

既然都看到这里了,点个赞呗,嘿嘿嘿。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。