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);
    memset(vis,0,sizeof(vis));
    for(int i=2; i<=m; i++)
     for(int j=i*i; j<=n; j+=i) vis[j]=1;
}
我们只用找到m=sqrt(n)内的素数和合数,然后对于1~n中的数如果输1~m中的 素数的倍数,则筛掉。

则判断L到R中素数的个数就也不是很难了。

对于这个题目来说

先把m=sqrt(n)中的素数和合数都求出来,对于L~R中的数进行一个判断。比如让你求1000到2000的结果。

先把1000/c[i]的值记为s,在吧2000/c[i]的值记为t,然后对于s到t之间我们用相应的素数c[i]乘s 到 相应的素数c[i]乘t 得到的值减去1000(这样有助于减少数组的大小)。

这样就把L~R的数组转换成了r数组,下面就是一个暴力的搜的过程了。

主要是一些细节的处理,比如1的处理,边界情况的处理,自己向来这种题目写的蛋疼...... 

#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstring>
#include<iostream>
#include<stdio.h>
#include<cstdlib>
#include<functional>
#include<cmath>
#define LL long long
using namespace std;

const int N=50000;
int Max=0xfffffff;
int a[50100];
int r[1000000],b[N+100],z=0;

int main()
{
    int a0,b0,i,j;
    for (i=2; i<=N; i++)
        if (!a[i])
        {
            b[++z]=i;
            for (j=i*2; j<=N; j+=i) a[j]=1;
        }
    while (cin>>a0>>b0)
    {
        memset(r,0,sizeof(r));
        int t=0,dis,mmax=-1,mmin=Max,m1,m2;
        for (i=1; i<=z; i++)
        {
            int s,t;
            s=(a0-1)/b[i]+1;
            t=b0/b[i];
            for (j=s; j<=t; j++)
                if (j>1) r[j*b[i]-a0]=1; //利用1~50000中的素数,把合数筛掉,转换成r数组
        }

        int k=-1;

        for (i=0; i<=b0-a0; i++)
            if (!r[i])  //若是质数
            {
                if (k!=-1)
                {
                    dis=i-k;
                    if (dis>mmax)
                        mmax=dis,m1=i+a0;
                    if (dis<mmin)
                        mmin=dis,m2=i+a0;
                }
                if (i+a0!=1) k=i;  //跳过1
            }
        if (mmax<0)
            cout<<"There are no adjacent primes."<<endl;
        else
        {
            cout<<m2-mmin<<','<<m2<<" are closest, ";
            cout<<m1-mmax<<','<<m1<<" are most distant."<<endl;
        }
    }
    return 0;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值