题目思路:费马平方和定理,一个奇素数可以分解为两个数的平方和,那么这个奇素素一定是 4k+1 型的。(注意特判下2)
所以我们筛素数的同时对每个数判断一下。
然后我们要剪枝和优化,大概如下几点:
1:偶数全部都不满足,直接算而不用放进筛法里。
2:只用用奇素数进行素数筛,而且只晒出没有偶数因子的数。
3:筛法和判定一个数是否满足题目的条件同时进行。
4:bool[3e8]的内存是不够的,我们需要用bitset优化,bitset的空间,关于这个,我请教了一下q巨。
所以我们一般在windows64 下可以节省8倍空间
然后记得处理一下细节,即2这个素数不满足4k+1 型,但是它也是满足a^2+b^2的。
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e8+10;
bitset<maxn>prime;
int Getprime(int l,int r)
{
int cnt=0;
if(l<=2&&2<=r) cnt++;
l=max(l,3);
if(l>r) return cnt;
if(l%2==0&&r%2==0) cnt-=(r-l+2)>>1;//减去偶数不满足的情况
else if(l%2&&r%2) cnt-=(r-l)>>1;
else if(l%2||r%2) cnt-=(r-l+1)>>1;
cnt+=r-l+1;
prime.reset();
prime[0]=true;
prime[1]=true;
int i;
for(i=3;i*i<=r;i+=2)
{
if(prime[i])
{
if(i>=l) cnt--;
continue;
}
if(i>=l&&(i-1)%4) cnt--;
for(int j=i*i;j<=r;j+=i<<1) prime[j]=true;
}
if(l%2==0) l++;
i=max(l,i);
for(;i<=r;i+=2)
{
if(prime[i]||(i-1)%4) cnt--;
}
return cnt;
}
int main()
{
int l,r;
while(~scanf("%d%d",&l,&r))
{
cout<<Getprime(l,r)<<endl;
}
}