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

 

 

-----------------------------------------------------------------------------------------------------------------

第一眼一看的时候

特别开心

这不就是求素数嘛!

看了一眼数据范围

还可以

用线性的欧拉筛应该可以

于是上手就写

(我才不会说我写了两遍,第二边上的时候思路才定下来)

好不容易写完了

结果输入数不进去

a[++l]写成了a[l++]

于是进入了死循环

好不容易过了样例

一提交t了5个点

啊哈??

不是线性的吗??(顿时懵逼)

于是看题解了(千万千万不要这样,动不动就看题解,真的是很不好的习惯)

题解居然是埃氏筛

啊哈??
再一看代码果然

先放一个我错误的代码!!!!!

以此为耻

#include<cstdio>
using namespace std;
long long n,m,a[1000005],b[1000005],c[1000005],ans,len; //a存每个区间的素数个数,b存素数 
long long l,r;

inline long long read()
{
    long long ans = 0;
    int p = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9')
    {
        if(ch == '-')
            p = -1;
        ch = getchar();
    }
    while(ch >= '0'&&ch <='9')
    {
        (ans *= 10)+= ch-'0';
        ch = getchar();
    }
    return ans * p;
}

int main()
{
    a[1] = 0;
    a[2] = 1;
    b[1] = 2;
    c[1] = 0;//0为不是 
    c[2] = 1;// 1为是 
    len = 1; 
    n = read();
    m = read();
    
    for(long long i=3;i<=m;i++)//遍历每个数 
        for(long long j=1;j<=len;j++)//看他能不能被素数整除 
        {
            if(i %  b[j]== 0) //被素数整除 
            {
                a[i]=a[i-1]; 
                break;
            }
            else
                if(j == len)//全用素数除过了 
                {
                    c[i] = 1;
                    a[i] = a[i - 1] + 1;
                    b[++len] = i;
                    break; 
                }
        }
        
    for(long long i = 1;i <= n;i++)
    {
        l = read();
        r = read();    
        if(l>=1&&r <= m)//在范围内 
        {
            if(c[l] == 1)
            {
                printf("%lld\n",a[r] - a[l]+1); 
            }
            else
            {
                printf("%lld\n",a[r]-a[l]);
            }
        }
        else
            printf("Crossing the line\n");
    }
    return 0;
}

 

 

哎确实是循环多了好多

还是放题解!!!!!!

#include<bits/stdc++.h>
using namespace std;

int f[1000001];
bool vis[1000001];

void shai(int n)
{
    f[1]=0;
    vis[1]=true;
    for(int i=2;i<=n;i++)
    {
        if(vis[i]==false) //在筛里进行前缀和
        {
            f[i]=f[i-1]+1;//前缀和计算 这处
            for(int j=i+i;j<=n;j=j+i)
            {
                vis[j]=true;//标记操作
            }
        }
        else f[i]=f[i-1];//前缀和转移 和这处就很妙了
    }
}

int main()
{
    int n,m;
    scanf("%d%d",&m,&n);
    shai(n);
    for(int i=1;i<=m;i++)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        if(l<1 || r>n) cout<<"Crossing the line"<<endl;//判断是否超出区间
        else 
        {
            int y=f[r]-f[l-1];//此处已经修改
            cout<<y<<endl;
        }
    }
    return 0;
}

换个角度从判断素数,变成判断合数;

埃氏筛

本质上就是从2开始把它除本身的倍数全部删去,以此类推

区间和可以用前缀和处理;


posted @ 2019-02-02 10:26  darrrr  阅读(151)  评论(0编辑  收藏  举报