题目:1007
一、复习几个数学常识(没忘的自动跳过)
1.自然数:从0开始的非负整数。
2.合数:自然数中除了能被1和本身整除外,还能被其他数(0除外)整除的数,最小合数4。
3.素(质)数:自然数中只能被1和本身整除的数,最小素数2。且对于一个数,其所有因子不超过它的平方。
4. 0和1不是素数,也不是合数。
二、优化版本,SVIP版
1.原理:
定义:prime[N+1]为bool类型M,N为任意的正整数。
prime[i]=true; // 表示i是素数
prime[i]=false; //i是合数
(1) 奇偶数筛选:对于大于2的偶数,他一定是合数。
(2) 倍数筛选法:一个素数的倍数一定是合数;如果prime[i]=true,表明i之前没有谁的倍数是i,即i不能被其之前的数整除,i为素数。
2.代码:
(1)C++版
#include<iostream>
#include<cmath>
using namespace std;
int main(){
long long n = 0;
cin >> n;
bool* prime = new bool[n+1]{false}; //开辟n+1个空间,才能取到prime[n]
prime[2] = true; //2为偶数且是素数,提前处理
//1.奇偶数筛选
for(long long i=3; i<=n; i+=2)
prime[i] = true;
//2.倍数筛选,偶数已经不用判断了
for(long long i=3; i<=sqrt(n); i+=2)
if(prime[i]) //i是素数
for(long long j=2*i; j<=n; j+=i)
prime[j] = false;
//3.统计素数对个数:双指针法
long long pre = 0; //前一个素数
long long next = 0; //后一个素数
long long count = 0; //统计个数
for(long long i=0; i<=n; ++i)
if(prime[i])
if(pre==0)
pre = i;
else{
next = i;
if(next-pre == 2)
++count;
pre = next;
}
cout << count << endl;
delete[] prime;
return 0;
}
(2)C语言版
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<stdbool.h>
int main(){
long long n = 0;
int count = 0;
scanf("%lld",&n);
bool *prime = (bool*)malloc(sizeof(bool)*(n+1));
prime[0] = prime[1] = false;
prime[2] = true;
//从3开始,奇数下标为true,偶数下标为false,大于2偶数是合数,可直接筛掉
for(long long i=3; i<=n; ++i)
if(i%2)
prime[i]=true;
else prime[i]=false;
//把为false的数的倍数筛掉(偶数),只需判断奇数下标即可
for(long long i=3; i<=sqrt(n); i+=2)
if(prime[i])
for(int j=2*i; j<=n; j+=i) //把素数i的倍数筛掉
prime[j]=false;
long long pre = 0;
long long next = 0;
for(long long i=0; i<=n; ++i)
if(prime[i]){
if(pre==0)
pre = i;
else {
next = i;
if(next-pre == 2)
++count;
pre = next;
}
}
printf("%d\n",count);
free(prime);
return 0;
}
效率对比:
三、普通版本
#include<iostream>
#include<cmath>
using namespace std;
bool isPrime(long long n){
for(long long i=2; i<=sqrt(n); ++i) //i的所有因子不超过n的开方
if(n%i==0)
return false;
return true;
}
int main(){
long long n=0;
long long pre = 3; //前一个素数
long long next = 0; //后一个素数
long long count = 0;
cin >> n;
for(long long i=5; i<=n; i+=2) //跳过偶数
{
bool flag = isPrime(i);
if (flag){ //i是素数
next = i;
if(next-pre==2)
count++;
pre = next;
}
}
cout << count << endl;
return 0;
}
效率:
对于一亿的数据,差别就已经很大了,以后大家记得写SVIP版。