poj 2689 素数筛选的巧妙使用

题目:

给出一个区间[L,R]求在该区间内的素数最短,最长距离。 (R < 2 * 10^9 , R - L <= 10 ^ 6)

由数论知识可得一个数的因子可在开根号内得到。所以,我们可以打出5*10^4内得素数。然后,在用一次筛法把在[L,R]内得合数找到,则剩下的就是素数了。这里要用到离散化,把一个数 x - L 保存在数组里。因为,直接保存肯定不行,但是我们发现区间特点较小。所以,可以想到离散化。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

typedef long long LL;
const int MAXN = 50000;
int primes[MAXN];
bool vst[MAXN];
int notPrimes[1000010];
int pos[1000010];
int top,pcnt;

void init(){
    top = 0;
    memset(vst,0,sizeof(vst));
    vst[0] = vst[1] = 1;
    for(int i = 2;i < MAXN;++i)if(!vst[i]){
        primes[top++] = i;
        for(int j = i + i;j < MAXN;j += i) vst[j] = 1;
    }
    //printf("top: %d\n",top);
}

void solve(int L,int R){
    memset(notPrimes,0,sizeof(notPrimes));

    if(L == 1) L = 2;              /// 防止筛掉所有该区间的素数本身!!!!!
    for(int i = 0;i < top&&(LL)primes[i]*primes[i] <= R;++i){  //筛选因子
        int s = L / primes[i] + (L % primes[i] > 0); //当前素数的最小倍数达到L

        s = (s == 1 ? 2 : s);    /// 防止筛掉所有该区间的素数本身!!!!!

        for(int j = s;(LL)j*primes[i] <= R;++j){
            if((LL)j*primes[i] >= L)   //合数
               notPrimes[j*primes[i] - L] = 1;   // 相当与离散化
        }
    }

    pcnt = 0;
    for(int i = 0;i <= R - L;++i){
        if(!notPrimes[i]){
            pos[pcnt++] = i + L;
            //printf("i -- > %d\n",i + L);
        }
    }

    if(pcnt < 2){
        puts("There are no adjacent primes.");
    } else {
        int minl,minr,maxl,maxr,minv = 999999,maxv = -1;
        for(int i = 1;i < pcnt;++i){
            if(pos[i] - pos[i-1] > maxv){
                maxv = pos[i] - pos[i-1];
                maxl = pos[i-1];
                maxr = pos[i];
            }
            if(pos[i] - pos[i-1] < minv){
                minv = pos[i] - pos[i-1];
                minl = pos[i-1];
                minr = pos[i];
            }
        }
        printf("%d,%d are closest, %d,%d are most distant.\n",minl,minr,maxl,maxr);
    }
}
int main()
{
    init();
    int L,R;
    while(~scanf("%d%d",&L,&R)){
        solve(L,R);
    }
    return 0;
}
时间: 2024-10-22 09:32:33

poj 2689 素数筛选的巧妙使用的相关文章

POJ 2689 Prime Distance 素数筛选法应用

题目来源:POJ 2689 Prime Distance 题意:给出一个区间L R 区间内的距离最远和最近的2个素数 并且是相邻的 R-L <= 1000000 但是L和R会很大 思路:一般素数筛选法是拿一个素数 然后它的2倍3倍4倍...都不是 然后这题可以直接从2的L/2倍开始它的L/2+1倍L/2+2倍...都不是素数 首先筛选出一些素数 然后在以这些素数为基础 在L-R上在筛一次因为 R-L <= 1000000 可以左移开一个1百万的数组 #include <cstdio>

poj 2689 大范围内素数筛选

1 /** 2 给定一定范围求其内的素数 3 4 注意: 5 **/ 6 7 #include <iostream> 8 #include <math.h> 9 #include <cstring> 10 using namespace std; 11 #define maxn 1000000 12 long long prime[500000]; 13 long long cprime[500000]; 14 long long isprime[maxn+100];

POJ 2689 Prime Distance(素数筛选)

题目链接:http://poj.org/problem?id=2689 题意:给出一个区间[L, R],找出区间内相连的,距离最近和距离最远的两个素数对.其中(1<=L<R<=2,147,483,647) R - L <= 1000000 思路:数据量太大不能直接筛选,要采用两次素数筛选来解决.我们先筛选出2 - 50000内的所有素数,对于上述范围内的数,如果为合数,则必定有2 - 50000内的质因子.换一句话说,也就是如果一个数没有2 - 50000内的质因子,那么这个数为素

POJ 2689 二次筛选(映射)

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12303   Accepted: 3296 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

POJ 3978 Primes(素数筛选法)

题目 简单的计算A,B之间有多少个素数 只是测试数据有是负的 //AC //A和B之间有多少个素数 //数据可能有负的!!! #include<string.h> #include<stdio.h> //素数筛选法 int pri[100000+10];//1 合数, 0 素数 void Prime() { memset(pri,0,sizeof(pri)); pri[1]=pri[0]=1; for(int i=2;i<50002;i++) { if(pri[i]==0)

poj 2689 Prime Distance 【数论】【筛法求素数】

题目链接:传送门 题目大意: 给你L和R两组数,L和R的范围是2^32,其间隔(即R-L最大为1,000,000.) .让你求出L和R之间素数的最大间隔和最小的间隔. 比如 2 17.之间的最小素数间隔是2 3,最大的素数间隔是11 17. 要是直接进行一个2^32次方筛法然后在判断是会T的. 我们这样来想,筛法求素数的原理是什么: /**vis数组标记为0则说明是素数*/ int vis[10005]; void getPrimevis(int n) { int m=sqrt(n+0.5);

POJ 2262 Goldbach&#39;s Conjecture(素数筛选法)

Description In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture: Every even number greater than 4 can be written as the sum of two odd prime numbers. For example: 8 =

hdu 5407 CRB and Candies(素数筛选法,除法取模(乘法逆元))

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5407 解题思路: 官方题解: The problem is just to calculate g(N) =\ LCM(C(N,0), C(N,1), ..., C(N, N))g(N) = LCM(C(N,0),C(N,1),...,C(N,N)). Introducing function f(n) =\ LCM(1, 2, ..., n)f(n) = LCM(1,2,...,n), the

O(N)的素数筛选法和欧拉函数

首先,在谈到素数筛选法时,先涉及几个小知识点. 1.一个数是否为质数的判定. 质数,只有1和其本身才是其约数,所以我们判定一个数是否为质数,只需要判定2~(N - 1)中是否存在其约数即可,此种方法的时间复杂度为O(N),随着N的增加,效率依然很慢.这里有个O()的方法:对于一个合数,其必用一个约数(除1外)小于等于其平方根(可用反证法证明),所以我们只需要判断2-之间的数即可. bool is_prime(int num) { const int border = sqrt(num); for