题目链接: 传送门
题目大意: 给你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; }
poj 2689 Prime Distance 【数论】【筛法求素数】,布布扣,bubuko.com
poj 2689 Prime Distance 【数论】【筛法求素数】
原文地址:http://blog.csdn.net/u010468553/article/details/38398115