Help Hanzo LightOJ - 1197 大数质数的优化筛法及错误原因(数论专题)

求区间[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的问题,可能是你的数组下标并没有处理好,而不是一味的找数组大小的 问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值