poj2689

这道题就是在区间中筛选素数,直接用筛选法会爆空间,每个数单独判断是不是素数,又会爆时间,所以就用了一个优化的筛选法,先算出数据范围每个合数可能的最小素因子,这样算每个区间是就不用再重复算这个素因子了,并且也不用每个数单独判断是不是素因子了,时间不超,空间也不超了,但是严格的时间复杂度的证明不会大哭

参考链接:

http://blog.csdn.net/a601025382s/article/details/12111297

http://www.cnblogs.com/kuangbin/archive/2013/05/20/3089840.html

(感觉国庆放假比暑假更凄凉。继续龙族系列大笑

(每个人都会有些理由,可以让你豁出命去。你留着命……就是等待把它豁出去的那一 天。 ——江南 《龙族》,是要为自己喜欢的事豁出去,不是要去犯罪!!!生气

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define N 1000010
#define M 65540
#define INF 0x3f3f3f3f

bool isprime[M];
int primenum[M];
bool issectionprime[N];
int sectionprime[N];
int cou;
int sectioncou;

void getprime(int a,int b){
    memset(issectionprime,true,sizeof(issectionprime));
    for(int i=0;(long long int)primenum[i]*primenum[i]<=(long long int)b&&i<cou;i++){//printf("%d %d\n",primenum[i],i);
        int l=a/primenum[i];

        if(a%primenum[i]){
            l++;
        }
        if(l==1){//注意:这里如果l=1的话,那么乘出来就是素数,而不是合数
            l++;
        }
        for(long long int j=l;j*primenum[i]<=(long long int)b;j++){
            issectionprime[j*primenum[i]-a]=false;
        }
    }

    if(a==1){
        issectionprime[0]=false;
    }
    sectioncou=0;
    for(int i=0;i<=b-a;i++){
        if(issectionprime[i]){
            sectionprime[sectioncou++]=a+i;
        }
    }

    return;
}

int main(){
    cou=0;
    memset(isprime,true,sizeof(isprime));
    //isprime[1]=false;
    for(int i=2;i*i<=M-1;i++){//把M写成了N,所以越界,造成primenum[0]=0
        if(isprime[i]){
            //primenum[cou++]=i;这句不能写里面,因为i最多遍历到i*i<=M-1,因此会造成大于sqrt(M-1)的素数没被加进primenum这个数组里
            /*if(i==3917){
                printf("hahaha\n");
            }*/
            //printf("%d %d\n",cou-1,primenum[cou-1]);
            for(int j=i+i;j<M;j=j+i){
                /*if(j==3917){
                    printf("hahaha\n");
                }*/
                isprime[j]=false;
            }
        }
    }
    //printf("%d\n",primenum[0]);
    for(int i=2;i<M;i++){
        if(isprime[i]){
            primenum[cou++]=i;
        }
    }

    int a,b;

    while(scanf("%d%d",&a,&b)!=EOF){
        getprime(a,b);
        int min=INF;
        int minnum;
        int max=-1;
        int maxnum;

        for(int i=0;i<sectioncou-1;i++){
            //printf("%d\n",sectionprime[i]);
            /*if(sectionprime[i]==2146841093||sectionprime[i]==2146841273){
                printf("%d %d\n",sectionprime[i],sectionprime[i+1]);
            }*/
            int jg=sectionprime[i+1]-sectionprime[i];
            if(jg<min){
                min=jg;
                minnum=i;
            }
            if(jg>max){
                max=jg;
                maxnum=i;
            }
        }
        //printf("%d\n",sectionprime[sectioncou-1]);

        if(max==-1){
            printf("There are no adjacent primes.\n");
        }
        else{
            printf("%d,%d are closest, %d,%d are most distant.\n",sectionprime[minnum],sectionprime[minnum+1],sectionprime[maxnum],sectionprime[maxnum+1]);
        }
    }

    return 0;
}


转载于:https://www.cnblogs.com/ahahah/p/4918180.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值