静下心来,慢慢调整自己的生活状态,一切都会好的。。。
关于等差素数列的问题,我们今天再做最后一次讨论,集百家之长,悟绝妙之道。。。
a.素数筛选法的精简进阶版本:(素数打表,减少不必要的重复计算)
//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
const int maxn=1000005;
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(1000000);
for(int d=1;d<=1000;d++){
for(int i=2;i<=100000;i++){
int j;
for(j=0;j<10;j++){
if(prime[i+j*d]){
break;
}
}
if(j==10){
cout<<d<<endl;
cout<<i<<endl;
return 0;
}
}
}
}
b.dfs版本:素数打表,用for循环从2开始递增,表示公差,里面的for循环表示从数j开始,用搜索判断是否数列是从j开始以i为公差,长度为10的等差数列。
//#include<bits/stdc++.h>
#include<iostream>
#include<cmath>
using namespace std;
int m,flag,k,s,prime[101000];
void dfs(int x,int n,int d){
if(n==9){
s=x;
flag=1;
return ;
}
if(flag==1){
return ;
}
if(k==1){
return ;
}
for(int j=x+1;j<=m;j++){
if(prime[j]-prime[x]>d){
k=1;
return ;
}
if(prime[j]-prime[x]==d){
dfs(j,n+1,d);
}
}
}
int main(){
int i,j;
m=0;
for(i=2;i<=100000;i++){
int p=0;
for(j=2;j<=sqrt(i);j++){
if(i%j==0){
p=1;
break;
}
}
if(!p){
prime[m++]=i;
}
}
flag=0;
for(i=2;i<=1000;i++){
for(j=2;j<m;j++){
k=0;
dfs(j,0,i);
if(flag==1){
cout<<i;
break;
}
}
if(flag){
break;
}
}
return 0;
}
c.总结dfs这种常规方法和特殊的素数筛方法,我们升级一下代码:
//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int m,flag,k,s,prime[10100],p[10100];
void dfs(int x,int n,int d){
if(n==9){
s=x;
flag=1;
return ;
}
if(flag==1){
return ;
}
if(k==1){
return ;
}
for(int j=x+1;j<=m;j++){
if(prime[j]-prime[x]>d){
k=1;
return ;
}
if(prime[j]-prime[x]==d){
dfs(j,n+1,d);
}
}
}
void isprime(){
for(int i=2;i<=10000;i++){
if(p[i]){
continue;
}
for(int j=i*i;j<=10000;j+=i){
p[j]=1;//减少重复判断剔除合数。
}
prime[m++]=i;
}
}
int main(){
int i,j;
isprime();
flag=0;
for(i=2;i<=1000;i++){
for(j=2;j<=m;j++){
k=0;
dfs(j,0,i);
if(flag==1){
cout<<i;
break;
}
}
if(flag){
break;
}
}
return 0;
}
Tips:
为啥在isprime()
里的取值范围必须是10000???
因为i要取到一个很大的值,虽然这个值可能不是素数,但因为需要判断,所以要取到最大素数的所在位置。
d.用6的规律来剪枝,使得算法耗时降为原来的1/3。
//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int m,flag,k,s,prime[10100],p[10100];
void dfs(int x,int n,int d){
if(n==9){
s=x;
flag=1;
return ;
}
if(flag==1){
return ;
}
if(k==1){
return ;
}
for(int j=x+1;j<=m;j++){
if(prime[j]-prime[x]>d){
k=1;
return ;
}
if(prime[j]-prime[x]==d){
dfs(j,n+1,d);
}
}
}
bool isprime2(int num){
if(num==2||num==3){
return 1;
}
if(num%6!=1&&num%6!=5){
return 0;
}
for(int i=5;i*i<=num;i+=6){
if(num%i==0||num%(i+2)==0){
return 0;
}
}
return 1;
}
void isprime(){
for(int i=2;i<=10000;i++){
if(isprime2(i))
prime[m++]=i;
}
}
int main(){
int i,j;
isprime();
flag=0;
for(i=2;i<=1000;i++){
for(j=2;j<=m;j++){
k=0;
dfs(j,0,i);
if(flag==1){
cout<<i;
break;
}
}
if(flag){
break;
}
}
return 0;
}
e.根据素数规律从30开始取公d为6的倍数,即d+=6,再次优化代码。
//#include<bits/stdc++.h>
#include<iostream>
using namespace std;
int m,flag,k,s,prime[10100],p[10100];
void dfs(int x,int n,int d){
if(n==9){
s=x;
flag=1;
return ;
}
if(flag==1){
return ;
}
if(k==1){
return ;
}
for(int j=x+1;j<=m;j++){
if(prime[j]-prime[x]>d){
k=1;
return ;
}
if(prime[j]-prime[x]==d){
dfs(j,n+1,d);
}
}
}
bool isprime2(int num){
if(num==2||num==3){
return 1;
}
if(num%6!=1&&num%6!=5){
return 0;
}
for(int i=5;i*i<=num;i+=6){
if(num%i==0||num%(i+2)==0){
return 0;
}
}
return 1;
}
void isprime(){
for(int i=2;i<=10000;i++){
if(isprime2(i))
prime[m++]=i;
}
}
int main(){
int i,j;
isprime();
flag=0;
for(i=30;i<=1000;i+=6){
for(j=2;j<=m;j++){
k=0;
dfs(j,0,i);
if(flag==1){
cout<<i;
break;
}
}
if(flag){
break;
}
}
return 0;
}
以上就是我对等差素数列这个问题的所有总结和探讨,对于一道普通的填空题,我觉得我自己挖的已经比较深了,嗯。。。先就这样好了,我要开始刷下一题了~