靜下心來,慢慢調整自己的生活狀態,一切都會好的。。。
關於等差素數列的問題,我們今天再做最後一次討論,集百家之長,悟絕妙之道。。。
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;
}
}
}
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;
}
以上就是我對等差素數列這個問題的所有總結和探討,對於一道普通的填空題,我覺得我自己挖的已經比較深了,嗯。。。先就這樣好了,我要開始刷下一題了~