- 定位:2017年第八届蓝桥杯省赛C/C++ B组试题B
- 原题:等差素数列
2,3,5,7,11,13,…是素数序列。
类似:7,37,67,97,127,157 这样完全由素数组成的等差数列,叫等差素数数列。
上边的数列公差为30,长度为6。
2004年,格林与华人陶哲轩合作证明了:存在任意长度的素数等差数列。
这是数论领域一项惊人的成果!
有这一理论为基础,请你借助手中的计算机,满怀信心地搜索:
长度为10的等差素数列,其公差最小值是多少?
注意:需要提交的是一个整数,不要填写任何多余的内容和说明文字。 - 属性:素数问题+模拟推理
- 难度:初级
- 独白:
虽然题意很好理解,但要是真的码对还真不容易啊啊啊啊啊
首先我们对长度为10的等差素数列进行一个合理的估值,嗯。。。大概估量不超过100000吧,于是我们开一个长度为100000的数组,这里我们采用素数筛来提高代码的运行效率,然后进行等差素数列的模拟。我们需要注意的细节是:
a.在素数筛中我们在第一个for循环后添加if(!prime[i])
判断的原因是为了减少重复标记,降低算法的时间复杂度。
b.我们在主函数中的or循环中,首项不超过10000的原因在于100000是其界限,而公差不超过1000的原因也是因为nxd受限于100000这个界限。
c.我们将公差循环放在最内层是因为这样我们可以减少判断次数。如果公差循环我们放在最外层,那么判断次数就是209x10000次,而我们将公差循环放内层,那么计算次数只需要判断198x1000次,这样降低了算法的时间复杂度,而且这样设计我们在一开始就可以对首项进行判断,如果首项不是素数,那么我们直接将其踢出循环,这样设计才是最省时间的设计,比网上大部分的那种吧公差循环放最外层的做法,效率高了好多的好哇!(210) - 代码:
#include<iostream>
using namespace std;
const int maxn=100005;
int prime[maxn];
void isprime(int n){
for(int i=2;i*i<=n;i++){
if(!prime[i]){
for(int j=i*i;j<=n;j+=i){
prime[j]=1;
}
}
}
}
int main(){
isprime(100000);
for(int a1=2;a1<=10000;a1++){
if(prime[a1]){
continue;
}
for(int d=2;d<=1000;d++){
int n;
for(n=1;n<10;n++){
if(prime[a1+d*n]){
break;
}
}
if(n==10){
cout<<a1<<endl;
cout<<d<<endl;
return 0;
}
}
}
}
- 总结:素数筛的使用和模拟推理中合理且省时的设计无不体现着算法讲究高效的原则。
- 感悟:心宽一点好了,没必要对傻子较量和赌气,也没必要对生活中遭遇的不合理而郁郁寡欢,认真活好自己的每一天,每一分,每一秒才是天道。
- 归档:已归档。