C语言算法——求解素数时间复杂度优化
题目:
让我们定义dn 为:dn=pn+1−pn,其中pi 是第i个素数。显然有d1=1,且对于n>1有dn是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”
现给定任意正整数N(<10^5 ),请计算不超过N的满足猜想的素数对的个数。
输入格式:
输入在一行给出正整数N。
输出格式: 在一行中输出不超过N的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
根据一般的思想,我们在求解素数的时候的常规思路就是:
(1):定义int变量i,j,然后进行双层的for循环进行逐一排查。
(2):将i从3到输入的数字n逐一进行除余操作
(3):当最后的接举例结果j==i的时候,即为一个素数
例如下面这段代码:
#include <stdio.h>
int main(){
int n;
scanf("%d",&n);
int i,j,cnt=0;
int pre=2;
for(i=3;i<=n;i++)//从第二个素数开始遍历
{
for(j=2;j<i;j++)
{
if(i%j==0)//判断不是素数
break;
}
if(j==i)
{
if(i-pre==2)//相邻素数相差2
cnt++;//计数
pre=i;//素数替换
}
}
printf("%d",cnt);
return 0;
}
--------------------------------!!!ERROR!!!----------------------------
但是这样的代码,显而易见可以发现,代码的运行时间过长,得不到较好的优化。
下面我将展示一种优化方式,可以在有效提高代码的运行速度。
老规矩,先附上代码:
#include <stdio.h>
#include <math.h>
int main(){
int n;
scanf("%d",&n);
int i,j,cnt=0;
int pre=2;
for(i=3;i<=n;i++)
{//从第二个素数开始遍历
for(j=2;j<=(int)sqrt(i);j++)//对所需要判断的整数i进行开方操作,达到减小范围的效果,优化算法时间
if(i%j==0)
break;
if(j>(int)sqrt(i))
{
if(i-pre==2)
cnt++;
pre=i;
}
}
printf("%d",cnt);
return 0;
}
这里解释下为什么可以直接通过sqrt函数进行省略部分数字的判断。 因为开方过后,从sqrt(i)之后的一半数据可以通过倍数对称的形式进行排除。
以上是博主对此次程序的优化,博主只是一个初步接触算法的小白。如果有什么逻辑不完善的地方,希望各位大佬可以给出改进意见,谢谢!