C++ P1865 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

题目地址:https://www.luogu.org/problemnew/show/P1865


个人思路:

  • 第一眼看过去感觉是个线性筛的裸题,不过发现还附带了一个区间查询
  • 关于区间查询的实现方式,粗略地想了一下,感觉DP的方式不是太好写,就写了一个树状数组

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int n,m;
int vis[1000001];
int tr[1000001];
int lowbit(int a){
    return a&-a;
}
int add(int a,int x){
    for(int i=a;i<=m;i+=lowbit(i))tr[i]+=x;
}
int sum(int a,int b){
    if(a>b)swap(a,b);
    int ans=0;
    for(a--;a;a-=lowbit(a))ans-=tr[a];
    for(;b;b-=lowbit(b))ans+=tr[b];
    return ans;
}
int main(){
    cin>>n>>m;
    memset(vis,0,sizeof(vis));
    int total=sqrt(m+0.5);
    vis[1]=1;
    add(1,1);
    for(int i=2;i<=total;i++)
        if(!vis[i])
            for(int j=i*i;j<=m;j+=i)
                if(!vis[j]){
                    vis[j]=1;
                    add(j,1);
                }
    for(int i=1;i<=n;i++){
        int ta,tb;
        cin>>ta>>tb;
        if(ta>tb)swap(ta,tb);
        if(tb>m||ta>m||ta<1||tb<1){
            printf("Crossing the line
");
            continue;
        }
        cout<<tb-ta+1-sum(ta,tb)<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680680.html