M - Help Hanzo LightOJ - 1197 (大区间求素数)

Posted wtsruvf

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了M - Help Hanzo LightOJ - 1197 (大区间求素数)相关的知识,希望对你有一定的参考价值。

题意:

求[a,b]之间的素数的个数

数很大。。。数组开不起

所以要想到转化

因为小于等于b的合数的最小质因子 一定小于等于sqrt(b),所以只需要求出来[0,sqrt(b)]的素数  然后取倍数删去[a,b]之间的合数  就好了

那  为什么小于等于b的合数的最小质因子 一定小于等于sqrt(b)呢?

因为b是最大的, 所以只讨论b即可 我们来看b的因子 。。一定是从 [0,sqrt(b)] 和 [sqrt(b),b]这两个区间里各取一个

先来看[0,sqrt(b)] 如果在这里取得是一个合数 则这个合数可由比它小的质数组成  所以只讨论质数即可  然后求倍数。。删除[a,b]之间的合数

为什么不看 [sqrt(b),b]  因为如果取一个这个区间的数去求倍数删除[a,b]之间的合数的话 ,这个倍数一定是在 [0,sqrt(b)]这个区间的。。。

所以小于等于b的合数的最小质因子 一定小于等于sqrt(b)

代码如下:

 

#include <iostream>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define MOD 2018
#define LL long long
#define ULL unsigned long long
#define maxn 100009
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define _  ios_base::sync_with_stdio(0),cin.tie(0)
//freopen("1.txt", "r", stdin);
using namespace std;
const int LL_INF = 0x7fffffffffffffff,INF = 0x3f3f3f3f;
LL primes[maxn];
bool vis[maxn], bz[maxn];
int ans = 0;
void init()
{
    mem(vis,0);
    vis[1] = 1;
    for(int i=2; i<maxn; i++)
        if(!vis[i])
        {
            primes[ans++] = i;
            for(LL j=(LL)i*i; j<maxn; j+=i)
                vis[j] = 1;
        }
}

int main()
{
    init();
    int T;
    int kase = 0;
    LL a, b;
    cin>> T;
    while(T--)
    {
        int res = 0;
        mem(bz,0);
        cin>> a >> b;
       // if(a <= 2) a = 2;
        int len = b - a;
        for(int i=0; i<ans && primes[i] * primes[i] < b; i++)
        {
            int j = a/primes[i];     
            if(j*primes[i] < a) j++;  // 我们要找到第一个大于等于a的合数,因为出的时候是向下取整  所以要判断一下
            if(j <= 1) j++;           // 如果j == 1 则说明 a是一个质数 但我们要找合数 
            {
                bz[j*primes[i] - a] = 1;
                j++;
            }

        }
        if(a == 1) bz[0] = 1;     // a == 1时要特殊讨论  因为1不是一个合数,无法由比它小的质数组成,也不是一个质数,所以在标记bz数组时 没有标记 就会多算  
        for(int k=0; k<=len; k++)
            if(!bz[k])
                res++;
        
        printf("Case %d: %d
",++kase,res);

    }

    return 0;
}

 

 

 

 

以上是关于M - Help Hanzo LightOJ - 1197 (大区间求素数)的主要内容,如果未能解决你的问题,请参考以下文章

Help Hanzo (LightOJ - 1197) 简单数论筛区间质数 (未完成)

LightOJ 1197 Help Hanzo(区间素数筛法)

B - Help Hanzo (LightOJ - 1197)

Light oj 1197 - Help Hanzo (素数筛技巧)

Help Hanzo (素数筛+区间枚举)

LightOJ1191 Bar Codes(DP)