一、题目要求如下:
二、解题思路
我想到的是暴力枚举,即列举出一定数量的、足够多的可能性,直接暴力枚举出所有情况;
题目要求是:
1、求10个素数组成的等差数列
2、等差数列的公差要求是最小的
这里首先需要先提前定义一个判断是否为素数的函数。
素数的条件是:
1、除了1和这个数本身,不能被其他数整除
2、0不是素数
例如:2、3、5、7这些数字都只能被1或者被它本身整除。其他任何数字除都不能除尽。
求素数的函数定义如下:
为什么要用到sqrt呢?
sqrt()是数学函数库中的求根函数,要使用的话得在包含头文件的位置声明包含<math.h>
sqrt()是求平方根的函数,例如:sqrt(9)=3;
而一个数字如果除以小于自身的平方根的整数都不能除尽,说明后面的数字就没有意义再求了。这样能大大减少程序的时间复杂度。
其实也可以不用,直接i<n也行,但是这样的运行时间会多很多。
num()函数可以求当前数字是否是素数,是就返回1,不是就返回0;
例:num(5)=1;num(4)=0;
我们需要得到一个等差数列,而等差数列就是一个递增或者递减的数列,其中每个数字的差值都是相同的,这个差值我们称之为公差。例如:1、3、5、7、9就是一个等差数列,公差为1;
而这个等差数列中的第一个数字称为第一项
所以我们用两个循环,分别枚举出大量的第一项素数和大量的公差。
并且对每个第一项都重复全部公差,看看能否有那么一个公差能累加出10个等差素数。
第一层循环i:列举第一项
第二层循环j:列举这个项的公差
第三层while循环:累加公差,若超过10个或者加到的下一个数字不是素数的时候跳出来这层循环
主要框架:
for(列举从2~n,每个都是第一项){
for(列举从2~n,每个都是一个公差){
while(当前项+公差是否为素数){是素数就累加公差;并且记录下来有多少个等差项了;如果超过了10个就跳出循环;}
if(刚好10个等差素数){跳出循环;}
}
if(刚好10个等差素数){跳出循环;}
}
三、代码实现
#include <stdio.h>
#include <math.h>
//判断是否是素数
bool num(int n){
int i;
if(n==1||n==0){
//printf("不是素数\n");
return 0;
}
for(i=2;i<sqrt(n);i++){
if(n%i==0) {//printf("不是素数\n");
return 0;
}
}
return 1;
}
int main()
{
// i为枚举出来的数字,不一定为素数
// j为枚举出来的公差,每个i都执行2-50000的方差,看看下一个数字是否为素数
// k为存储i的临时变量,因为在累加10个素数等差数列的时候需要重复加公差,不能影响i的值,否则影响枚举数字的这层循环
int i,j,k,n=1;
//枚举数字2-50000
for(i=2;i<50000;i++){
if(num(i)){//如果i为素数
k=i;//k为临时变量存储i
//第二层循环枚举2-50000的方差。每次都将第一个素数+方差,看看是否还是素数,当累计到10个即满足题目要求
for(j=2;j<50000;j++){
k=i;//重置k,为什么要这个呢?因为当出现n>10的情况,就是说数列可能不止10个的情况,或者没到10个就退出来的情况,需要重置k值为i,不然就一直累加下去了
while(num(k+j)){//若k+j为素数。k=i,而i是枚举的素数
k+=j;//k累加方差
n+=1;//n为该数列长度。即:当下包含多少个等差素数了
if(n>10) break;//当n>10时,意味着当前素数的当前等差值中,出现了不止10个的等差素数。题目要求是10个,不能是11个或以上
}
//执行到该行说明已经遍历完了一个等差素数数列,该等差数列个数满足n>=10,所以要判断是否是10个,是的话跳出循环,不是继续找
if(n==10) break;
n=1;//重置数列个数
}
//这个也是必须的,不然这层循环跳不出去
if(n==10) break;
}
}
printf("%d",j);
return 0;
}