要求
输入任意两个正整数A和B,求这两个数之间有多少个素数(包含A和B)。规定取值范围为A ≤ B < 10^5,当 A = B = -1时退出程序。
Input
0 9999
2 10
-1 -1
Output
1229
4
这个题本质上就是求素数,一共有两种方法:
方法一:试除法
对于大于1的正整数a,如果a具有小于或等于sqrt(a)的素因子,则a为合数,否则a为素数。
因此,可用区间 [2,sqrt(a)] 内的数去试除a,只要有一个数能整除a ,则a为合数,否则a为素数。这种判断素数的方法就是试除法。
复杂度O(sqrt(n))
代码如下:
#include <iostream>
using namespace std ;
long f_sushu(long x,long y)
{
long i,j,n=0;
if(y<=1) // 输入最大的数小于2,素数个数为0
return n;
if(x<=1) // 若X的值小于2,从2开始算素数个数
x=2 ;
for(i=x;i<=y;i++)
{
for(j=2;j*j<=i;j++)
if(i%j==0)
break; // 可以除尽为合数
if(j*j>i)
n++;
}
return n ;
}
int main ()
{
long x,y,t;
while(cin >> x >> y)
{
if(x==-1 && y==-1)
break ;
cout << f_sushu(x,y) << endl ;
}
return 0;
}
方法二:筛法求素数
如果要判断一个区间内的数是否为素数,也可用筛法求素数。
算法思想:
1)将所有候选数2~n放入筛中;
2)找出筛中最小数P,P一定为素数。
3)宣布P为素数,并将P的所有倍数从筛中筛去;
4)重复2)至3)直到筛空.
其实,当P>sqrt(n)时筛中剩下的数就已经都是素数了。
1.例如可以列一个数组X[N],初始值都为0,从X[2]开始,将2的倍数在数组中依次赋值1(可知一个素数的倍数一定为合数),接下来判断是从下一个值为0的数开始将其倍数依次赋1,重复操作直到区间尾。
2.或者可以在该位置赋值为它之前有多少个素数,这样任意两个数之间的素数个数可以直接表示为X[b]-X[a] 。
代码如下(采用2的形式)
#include <iostream>
#include <cmath>
#define N 100001
using namespace std ;
long long fun(long long a, long long b)
{
long long x[N]={0},i,j;
long long t=0;
for(i=2 ;i<=b ;i++)
{
if(!x[i]) //值为0的数
{
t++; // t用来记录有多少个素数
x[i]=t;
for(j=2*i ;j<=b ;j+=i)
x[j]=1;
}
x[i]=t; //合数则赋值与前一个相同的值
}
if(a>1 && x[a]!=x[a-1]) //注意直接减去的话若前一个数是素数,则结果会多减去一个,所以要加回来
return x[b]-x[a]+1 ;
return x[b]-x[a] ;
}
int main ()
{
long long a,b,n;
while(cin >> a >> b)
{
if(a==-1 && b==-1)
break ;
if(b<=1)
n=0 ;
else
n=fun(a,b);
cout << n << endl ;
}
return 0 ;
}
这个代码其实用不到long long 型,可以换小一点的🧐
要注意进行判断的条件 x[a]!=x[a-1] ,表示数a本身是一个素数,切记切记别在搞错了…