素数求解方法及其优化

题目:

请实现一个函数,对于给定的整型参数N,依次打印出小于N的素数。

解法一:试除法

由素数的定义我们很自然的会想到如下代码:

#include <stdio.h>

void print_prime(int n)
{
	int i=0;
	for(i=2;i<=n;i++)
	{
		int j=0;
		for(j=2;j<i;j++)
		{
			if(0==i%j)
				break;
		}
		if(j==i)
			printf("%d\t",i);
	}
}

int main()
{
	int num=0;
	scanf("%d",&num);
	print_prime(num);
	return 0;
}

在上面的代码中,我们看到在判断素数时一直从2试除到n-1。这里从n/2之后的数到n-1的试除显然是多余的,比如某个数不能被3整除,必然不能被6整除。

优化1:

试除的范围优化到[2,n/2],这样一下子就将工作量减少了一半,代码如下:

void print_prime(int n)
{
	int i=0;
	for(i=2;i<=n;i++)
	{
	        int j=0;
		for(j=2;j<=i/2;j++) //修改部分
		{
			if(0==i%j)
				break;
		}
		if(j==(i/2+1))  //修改部分
			printf("%d\t",i);
	}
}

既然能将试除范围优化到[2,n/2],那么这个范围是不是还能优化呢?答案是可以的,在[2,n/2]这个范围里(√n,n/2]的试除也是多余的。因为因数是成对出现的,比如16可分解为:1和16 、2和8、4和4、8和2、16和1。这些因数里必然有一个小于等于4。所以只需试除小于等于√n的数就可以了。

优化2:

试除范围优化为[2,√n],代码如下:

#include <stdio.h>
#include <math.h>

void print_prime(int n)
{
	int i = 0;
	for (i = 2; i <= n; i++)
	{
		int j = 0;
		for (j = 2; j <= sqrt(i); j++) //修改部分
		{
			if (0 == i%j)
				break;
		}
		if (j >sqrt(i))         //修改部分
			printf("%d\t", i);
	}
}

int main()
{
	int num = 0;
	scanf("%d", &num);
	print_prime(num);
	return 0;
}

上面所有的代码在找素数的时候是从2到n,在这个范围内除了2之外的偶数都不是素数,所以我们可以跳过这些偶数。

优化3

寻找素数时跳过偶数,这样工作量就少了一半。代码如下:

void print_prime(int n)
{
	int i = 0;
	if (n >= 2)
		printf("%d\t", 2);
	for (i = 3; i <= n; i+=2)
	{
		int j = 0;
		for (j = 2; j <= sqrt(i); j++)
		{
			if (0 == i%j)
				break;
		}
		if (j >sqrt(i))
			printf("%d\t", i);
	}
}
时间: 2024-09-29 02:23:08

素数求解方法及其优化的相关文章

求100以内素数的5中基本方法及其优化

求100以内素数的5中基本方法及其优化方法1 基本做法 错解比较:进入了小循环:有时加pass也可以.错解:这里的print也同样注意不要写到循环内. 注释:1.两种条件运用:为合数.2.以上错误点.方法二 注释:1.条件运用,质数除了2都是奇数,因为偶数都能被除了自身外的2整除.改进自12.偶数除了2都不是质数.3.第二个for写的是到开方的奇数.4.奇数含有质数和非质数.偶数除了2一定不是质数.所以先剥离了偶数. 方法三:使用列表 注释:1.break continue pass2.质数i依

(素数求解)I - Dirichlet&#39;s Theorem on Arithmetic Progressions(1.5.5)

Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description If a and d are relatively prime positive integers, the arithmetic sequence beginning with a and increasing by d, i.e., a, a + d, a + 2d, a + 3d, a 

代码实现:判断101-200之间有多少个素数(质数),并输出所有素数。 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数。

package com.heima.Coding; /* 判断101-200之间有多少个素数(质数),并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数.*/ public class Test { public static void main(String[] args) { int count = 0; for (int i = 100; i < 200; i++) { for (int j = 2; j <=

判断素数的方法

判断n是否为素数 1.最简单的方法:用n除以2~sqrt(n),有一个能除尽就不是素数,否则是素数.时间复杂度:O(sqrt(n)) 为什么是sqrt(n),n的开方呢? 假设n是个合数,它必然可以由两个数a,b相乘而得到,即a*b = n.在这两个数中,如果a>sqrt(n), 则b<sqrt(n),同理b>sqrt(n), 则a<sqrt(n),若a=b即为a,b中最小的那个数的值最大的情况,a*a=n, 即a=sqrt(n). 所以可以证明 :如果我们要判断一个数n是素数还是

LIS的三种求解方法

1.  O(n^2) 传统的求解方法 ,思路为dp,状态转移方程为 dp[i]=max( dp[j]+1,1) 即到目前的i为止,对前面出现的a[j](j<i)进行遍历 ,如果出现了a[i]>a[j]的情况 ,就使用状态转移方程. 转移方程代表了两种可能 ,第一种为第i个元素自己成为一个上升的队列  ,或者是由于前面的a[j]<a[i]  所以在 dp[j]的基础之上形成了dp[i] = dp[j]+1  但前提是a[i]>a[j] # include <stdio.h>

最小公倍数的求解方法

一 写在开头 1.1 本节内容 本文的主要内容是介绍一种两个数最小公倍数(Lowest Common Multiple)的求解方法. 二 最小公倍数求法 2.1 算法原理 两个数的公倍数可以是无限多个,但最小公倍数只有一个.在前面的文章中介绍了两数最大公约数的求解方法.这里介绍一种两个数的最小公倍数的求法.其基于的原理是两个数的最小公倍数会等于两个数的乘积除以两个数的最大公约数的结果.即: LCM(a, b) = (a * b) / GCD(a, b) 下面结合最大公约数的求法使用C语言实现最小

加速ssh连接的方法(优化ssh服务)

目录 加速ssh连接的方法(优化ssh服务) 一.修改 /etc/ssh/sshd_config 二.修改被连接端的文件 /etc/nsswitch.conf 三.修改主动连接端的 /etc/hosts 四.查看连接过程 ssh -v 加速ssh连接的方法(优化ssh服务) 本文参考于https://www.cnblogs.com/fwdxl/p/6723820.html,在其基础上略做整理. 一.修改 /etc/ssh/sshd_config 经常出现ssh连接缓慢,让人误以为是ssh连接不上

数据库有百万数据量的情况下,分页查询的方法及其优化方式

当需要从数据库查询的表有上万条记录的时候,一次性查询所有结果会变得很慢,特别是随着数据量的增加特别明显,这时需要使用分页查询.对于数据库分页查询,也有很多种方法和优化的点. 下面简单说一下我知道的一些方法. 准备工作 为了对下面列举的一些优化进行测试,下面针对已有的一张表进行说明. 表名:order_history 描述:某个业务的订单历史表 主要字段:unsigned int id,tinyint(4) int type 字段情况:该表一共37个字段,不包含text等大型数据,最大为varch

c语言:实现对于给定的正整数N,依次打印出小于等于N的所有素数。两种方法及其优化

请编写一个程序,实现对于给定的正整数N,依次打印出小于等于N的所有素数. 方法一:试除法 由素数的定义得到如下程序: #include<stdio.h> int print_prime(int num)//prime表示素数 { int i = 0; for (i = 2; i <= num; i++) { int j = 0; for (j = 2; j < i; j++) { if (i%j == 0) { break; } } if (i==j) { printf("