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

其实就是想写写莫队练练(你信么),然而这个优雅的暴力还是超时一个点:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>

using namespace std;
const int N=1000010;

int answer[N],pos[N],become_answer;
bool vis[N];
int block,js,n,m; 
struct node{
	int l,r,num;
}E[N];

inline int read()
{
	int x=0;int f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
	return x*f;
}

inline void important()
{
	for(int i=2;i<=sqrt(N+1);i++)
		if(!vis[i])
			for(int j=i*2;j<=N;j+=i)
				vis[j]=1;
	vis[0]=vis[1]=1;
}

inline bool cmp(node a,node b)
{
	if(pos[a.l]==pos[b.l])
		return a.r<b.r;
	else
		return a.l<b.l;
} 

inline void add(int x)
{
	if(!vis[x])
		become_answer++;
}

inline void dale(int x)
{
	if(!vis[x])
		become_answer--;
}

inline void MD()
{
	int l=1,r=1;
	for(int i=1;i<=js;i++)
	{   int ll=E[i].l,rr=E[i].r;
		for(;l<E[i].l;l++)dale(l);
		for(;l>E[i].l;l--)add(l-1);
		for(;r>E[i].r;r--)dale(r);
		for(;r<E[i].r;r++)add(r+1);
		answer[E[i].num]=become_answer;
	}
}

int main()
{
	important();
	n=read(),m=read();
	for(int i=1;i<=n;i++)
	{
		int l=read(),r=read();
		if(l<1||r<1||l>m||r>m)
			answer[i]=-1;
		else
		{
			E[++js].l=l;
			E[js].r=r;
			E[js].num=i;
		}
	}
	block=sqrt(m);
	for(int i=1;i<=m;i++)
		pos[i]=(i-1)/block+1;
	sort(E+1,E+js+1,cmp);
	MD();
	for(int i=1;i<=n;i++)
		if(answer[i]==-1)
			printf("Crossing the line
");
		else
			printf("%d
",answer[i]);
			
	return 0;
}

 水一波前缀和:

#include <cstdio>
#include<iostream>
#include<algorithm>

const int N=1000005;
using namespace std;

int n,m,l,r,s[N];

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=2;i<=m;i++)s[i]=1;
    for(int i=2;i*i<=m;i++)
        for(int j=i+i;j<=m;j+=i)
            s[j]=0;
	for(int i=1;i<=m;i++)
         s[i]+=s[i-1];
    while(scanf("%d%d",&l,&r)==2)
        (l<1||r>m)?printf("Crossing the line
"):printf("%d
",s[r]-s[l-1]);
}