【清北前紧急补课8】A % B Problem

题目背景

题目名称是吸引你点进来的

实际上该题还是很水的

题目描述

区间质数个数

输入输出格式

输入格式:

一行两个整数 询问次数n,范围m

接下来n行,每行两个整数 l,r 表示区间

输出格式:

对于每次询问输出个数 t,如l或r∉[1,m]输出 Crossing the line

输入输出样例

输入样例#1: 复制
2 5
1 3
2 6
输出样例#1: 复制
2
Crossing the line

说明

【数据范围和约定】

对于20%的数据 1<=n<=10 1<=m<=10

对于100%的数据 1<=n<=1000 1<=m<=1000000 -10^9<=l<=r<=10^9 1<=t<=1000000

 

这个题不难看出用一般的判断素数的方法是会T的,那么我们就要尝试着用欧拉筛法。

我看别的题解都没有说易错的地方,我就点一下易错的点吧。

我的欧拉筛法跟别的有些不同的是用了vector

用bool数组np来记录不是素数的点,用vector p来记录是素数的点 数组ga[i]来计算前缀和,即i前的素数数。

void prime(){
    np[1]=true;
    vector<int>p;
    for(int i=2;i<=m;i++){
        if(!np[i]) p.push_back(i);
        for(int j=0;j<p.size()&&i*p[j]<=m;j++){
            np[i*p[j]]=true;
            if(i%p[j]==0) break;
        }
        if(!np[i]) ga[i]=ga[i-1]+1; //这两行是非常关键的,开始我就因为没有注意想当然的以为但pd到不是素数的就会直接break完全没有意识到跳出的是j那个循环。果然我还是太弱了
        else ga[i]=ga[i-1];
    }
}

全部代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
int n,m,l,r;
int t;
bool np[1000010];
int ga[1000010];

void prime(){
    np[1]=true;
    vector<int>p;
    for(int i=2;i<=m;i++){
        if(!np[i]) p.push_back(i);
        for(int j=0;j<p.size()&&i*p[j]<=m;j++){
            np[i*p[j]]=true;
            if(i%p[j]==0) break;
        }
        if(!np[i]) ga[i]=ga[i-1]+1;
        else ga[i]=ga[i-1];
    }
}

int main(){
    cin>>n>>m;
    prime();
    for(int i=1;i<=n;i++){
        cin>>l>>r;
        if(l<1||r>m||r<1||l>m) cout<<"Crossing the line"<<endl;
        else{
            cout<<ga[r]-ga[l-1]<<endl;
        }
    }
}

 

posted @ 2018-07-21 17:57  东方的古文明  阅读(109)  评论(0)    收藏  举报