求区间[a,b]有多少个素数
Input
多组输入,第一行是t表示有t组数据,接下来每行一对a,b
Output
输出"Case x:"后再输出答案
Sample Input
3
2 36
3 73
3 11
Sample Output
Case 1: 11
Case 2: 20
Case 3: 4
Note
t ≤ 200
1 ≤ a ≤ b < 2^31, b - a ≤ 100000
题目要求寻找a,b之间的质数个数。这a,b一看就知道不可能正常a到b找(虽然我试了一发但是肯定是T了)。然后我将2^31的sqrt的数值maxn进行打表,如果我最大的b小于maxn那我就直接按着表来找质数,找到符合大于a小于b的质数。
if(b<maxn){
for(ll i=0;i<cnt;i++){
if(pri[i]>=a&&pri[i]<=b)
ans++;
if(pri[i]>b) break;
}
printf("Case %d: %lld\n", ++cas,ans );
}
对于最小值都比我打的表数字来的大的情况,我让a开始的数所有数加上质数表上质数的倍数,一直到b结束。这样我再将ab之间所有的合数打上了标记,取其中的质数个数。
else{
memset(vis,0,sizeof(vis));
for(ll j=0;j<cnt;j++){
for(ll k=(a+pri[j]-1)/pri[j];k<=b/pri[j];k++){
if(k==1||k==0) continue;
vis[pri[j]*k-a]=true;
}
}
for(ll i=0;i<=b-a;i++)
if(!vis[i]) sum++;
printf("Case %d: %lld\n",++cas,sum);
}
具体的代码就不列了,错误的问题我再讲一下
如果我不对第二种情况下的数字进行打标记,而直接进行遍历。毫无疑问的是这种方法确实减少了复杂度,但是由于判断一个质数需要将所有质数表打到sqrt(n),才能得出sum++的条件所以会超时。
else{
for(ll i=a;i<=b;i++){
int flag=1;
for(ll j=0;j<cnt;j++){
if(sqrt(i)<pri[j]) break;
if(i%pri[j]==0){
flag=0;break;
}
}
if(flag) sum++;
}
printf("Case %d: %lld\n", ++cas,sum );
}
对于RE的问题,可能是你的数组下标并没有处理好,而不是一味的找数组大小的 问题