poj2689:素数筛

题目大意,给定l和u,求区间[l,u]内的素数中,相邻两个差最大和最小的素数其中 u的范围达到了2e9本质上需要找出n以内的所有素数,使用筛法。先保存50000(大于sqrt(2e9))内的所有素数,然后再去筛出区间[l,u]内的素数(题上给定l-u<=1000000)所以可以存下所有素数又由素数分布定理 素数个数s(n)~n/lnn并不是很大,所以找到所有素数保存在prime[]中扫一遍即可得到答案代码如下
#include<stdio.h>
#include<string.h>
#include <algorithm>
using namespace std;
#define N 100007
bool isprime0[50000];
int prime0[50000];
long long prime[100000];
bool isprime[1000010];
int num0;
int num;
long long x,y;
void setprime()
{
    num=0;
    for(int i=2;i<=50000;i++)
    {
        if(!isprime0[i])
            prime0[num0++]=i;
        for(int j=0;j<num0&&prime0[j]*i<=50000;j++)
        {
            isprime0[i*prime0[j]]=1;
            if(!(i%prime0[j]))
                break;
        }
    }
}
void setprime1()
{
    memset(isprime,0,sizeof(isprime));
    for(int i=0;i<num0;i++)
    {
        long long j=x/prime0[i];
        while(j*prime0[i]<x)
            j++;
        for(j=j*prime0[i];j<=y;j+=prime0[i])
            if(j/prime0[i]>1)
                isprime[j-x]=1;
    }
    if(x==1)
        isprime[0]=1;
    num=0;
    for(long long i=0;i<=y-x;i++)
    {
        if(!isprime[i])
            prime[num++]=x+i;
    }
}
int main()
{
    setprime();
    while(scanf("%I64d%I64d",&x,&y)!=EOF)
    {
        setprime1();
        long long a,b,c,d;
        long long mi=10000000,ma=0;
        if(num<2)
        {
            puts("There are no adjacent primes.");
            continue;
        }
        for(int i=0;i+1<num;i++)
        {
            long long p=prime[i+1]-prime[i];
            if(p<mi)
            {
                a=prime[i];
                b=prime[i+1];
                mi=p;
            }
            if(p>ma)
            {
                c=prime[i];
                d=prime[i+1];
                ma=p;
            }
        }
        printf("%I64d,%I64d are closest, %I64d,%I64d are most distant.\n",a,b,c,d);
    }
    return 0;
}
时间: 2024-10-05 05:50:20

poj2689:素数筛的相关文章

POJ 2635 The Embarrassed Cryptographer (同余线性方程+素数筛)

题目地址:POJ 2635 先用素数筛把10^6万以内素数筛出来.然后把输入的那个大数转化成数组,并且每三位存成一个数,这样可以节约内存和时间,然后利用同余线性的原理,对那个小整数以内的所有素数枚举,然后判断是否整除,找到最小的能被整除的. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #i

素数筛 模板

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 using namespace std; 6 7 int prim[3000000]={2,3,5}; 8 //素数是分为基本素数{2,3}.阳素数{6N+1,N>=1}形式的.阴素数{6N-1,N>=1}形式的 9 //为了代码的好写,在这里这样写的 : 10 //数除了{2,3,5}为素数,其他的数可以写成6N,6N+1

素数筛&amp;&amp;欧拉筛 BZOJ2818 Gcd BZOJ2190 [SDOI2008]仪仗队

折腾了一晚上很水的数论,整个人都萌萌哒 主要看了欧拉筛和素数筛的O(n)的算法 这个比那个一长串英文名的算法的优势在于没有多次计算一个数,也就是说一个数只筛了一次,主要是在%==0之后跳出实现的,具体的解释看的迷迷糊糊,特别是欧拉函数的求解 http://blog.csdn.net/lerenceray/article/details/12420725 代码如下 1 void ES(){ 2 for(int i=2;i<n;i++){ 3 if (!pd[i]){ 4 prime[++top]=

素数筛

这是我目前知道的打素数表最快的方法了----  差不多是O(n)的,100000以内花了0.005秒. 1 int prime[100005], np, vis[100005]; 2 3 void get_prime(int n){ 4 mset(prime); mset(vis); 5 np = 0; 6 for(int i = 2; i < n; i++){ 7 if(vis[i] != 1) 8 prime[np++] = i; 9 for(int j = 0, t; j < np &a

ACdream 1112 Alice and Bob (sg函数的变形+素数筛)

题意:有N个数,Alice 和 Bob 轮流对这些数进行操作,若一个数 n=a*b且a>1,b>1,可以将该数变成 a 和 b 两个数: 或者可以减少为a或b,Alice先,问谁能赢 思路:首先单看对每个数进行除法的操作,我们可以知道其实是在除以每个数的素因子或素因子之间的积 比如 70=2*5*7 我们可以变成 10(2*5)或 14(2*7) 或 35(5*7)或 2 或 5 或 7 或 1 这七种状态 当我们把他们(2,5,7)当作3个石子也就是一堆时,然而实际上我们是将这堆石子进行ni

最大公约数,最小公倍数,素数,素数筛

最大公约数 a.b的最大公约数是b,a%b的公约数,如果有一个等于0,最大公约数是a int gcd(int a,int n){ if (b==0) return a; else return gcd(b,a%b); } 或 return b!=0 ? gcd(b,a%b):a; 最小公倍数 是两数的乘积除以他们的最大公约数 素数筛 输出2-10000之间的所有素数 从2开始遍历,标记每个数的所有倍数为非素数 void sushu(){ for (int i=0;i<10000;i++){ ma

欧拉函数+素数筛

欧拉函数,就是欧拉发现的一个关于求素数的的公式,然后我们编个函数实现这个公式. 欧拉发现求小于等于n的正整数中有多少个数与n互质可以用这个公式: euler(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…(1-1/pn),其中p1,p2……pn为x的所有素因数,x是不为0的整数.euler(1)=1(唯一和1互质的数就是1本身). 欧拉公式的延伸:一个数的所有质因子之和是euler(n)*n/2. 其实直接看模板加注解想想就能看懂 筛选的原理就是找出n的因子,剔除含有

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

题目链接:http://lightoj.com/volume_showproblem.php?problem=1197 给你a和b求a到b之间的素数个数. 先在小区间素数筛,大区间就用类似素数筛的想法,把a到b之间不是素数的标记出来.因为b-a最多1e5的大小,所以每组数据的时间复杂度最多就o(1e5 log1e5). 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using names

HDU 1016 Prime Ring Problem (素数筛+DFS)

题目链接 题意 : 就是把n个数安排在环上,要求每两个相邻的数之和一定是素数,第一个数一定是1.输出所有可能的排列. 思路 : 先打个素数表.然后循环去搜..... 1 //1016 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 6 using namespace std ; 7 8 bool vis[21]; 9 int prime[42] ,cs[21]; 10 int n ; 11

HDU 4497 素数筛,合数分解

题意:给你两个数,G和L ,它们是一组数的GCD(最大公约数)和LCM(最小公倍数),求出满足条件的组合数,每个组合有三个数,排序不同,也算不同组合. L : p1^t1 * p2^t2 ... * pi^ti G: q1^s1 * q2^s2... * qi^si (pi和qii都是素数ii) G(最大公约数)里出现的所有数都要在L(最小公倍数)里出现,或者说L mod G=0,有人要问为什么了?其实仔细想想就清楚了,如果a,b,c的最小公倍数肯定可以被a,b,c任意一个整除,而他们的最大公约