uva_10140/poj_2689 Prime Distance(區間素數)
2015-06-27 20:17
330 查看
uva 題目鏈接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=35&page=show_problem&category=13&problem=1081&mosmsg=Submission+received+with+ID+15689014
題目大意:在給定範圍L和R,找到L和R範圍內差距最小和最大的兩對素數。1=< L<=R<=2,147,483,647,R-L<=1000000
分析:
區間素數,經典問題。因為最大是2^31-1,開根號為小於46341,所以可以先預處理做一遍素數篩選,篩出1~50000的素數,然後再用1~50000的素數去篩選任意L到R之間的素數。具體做法,可開一個a[]存所求區間的素數情況,求a[L]~a[R]之間的素數,就是求a[0]~a[R-L]之間的素數。
代碼:
關於質數的一些重要結論:
設pi(n)為小於等於n的質數個數,則pi(n)\approxn/n/ln(n)
當n在10^5到10^6左右時,質數的數量大概可以用10/n來估計。
第 n 個質數大約是 nln(n)
《计算机算法导引: 设计与分析》有講到質數的這部分
另外一種求大範圍質數的方法:
http://www.jiancool.com/article/50042575894/
題目大意:在給定範圍L和R,找到L和R範圍內差距最小和最大的兩對素數。1=< L<=R<=2,147,483,647,R-L<=1000000
分析:
區間素數,經典問題。因為最大是2^31-1,開根號為小於46341,所以可以先預處理做一遍素數篩選,篩出1~50000的素數,然後再用1~50000的素數去篩選任意L到R之間的素數。具體做法,可開一個a[]存所求區間的素數情況,求a[L]~a[R]之間的素數,就是求a[0]~a[R-L]之間的素數。
代碼:
#include<cstdio> #include<cstdlib> #include<cstring> using namespace std; #define range 50000 #define range2 1000010 #define INF 0xFFFFFFF typedef long long LL; int prime[range],is_prime[range]; int a[range2],prime2[range2]; int num_p; void produce_prime() { memset(is_prime,0,sizeof(is_prime)); num_p=0; for(int i=2;i<range;i++) { if(is_prime[i]==0) { int j=i+i; prime[num_p++]=i; while(j<range) { is_prime[j]=1; j+=i; } } } } int main() { // freopen("in.txt","r",stdin); LL left,r; produce_prime();//預處理先篩出50000以內的素數 while(scanf("%lld%lld",&left,&r)==2)//這裡如果用%d%d,在poj上會TLE,但是在uva上能AC { memset(a,0,sizeof(a)); if(left==1) { a[0]=1; //如果L=1,它不能算做素數,此處特判 } for(int i=0;i<num_p && prime[i]*prime[i]<=r;i++)//從最小的素數開始,循環要小於素數個數和小於R的開根號 { int k=(int)left/prime[i];//從prime[i]的倍數開始篩,並且這個倍數要大於等於left,k為prime[i]的幾倍 LL m=k*prime[i]; while(m<left || k<=1) //因為k是整除得來,所以如果left不是prime[i]的整數倍,多餘的部分就會被去掉,或者出現left<prime[i]的情況;還有就是正好left是素數,k=1,此時left不能被篩掉,所以要讓k>1而且m>=k { m+=(LL)prime[i]; k++; } for(LL j=m;j<=r;j+=prime[i]) { if(j>=left)//開始用素數篩,將left~r中prime[i]的倍數篩掉,因為left,r可能很大,這裡用了一個**偏移的index**的技巧,即a[j]=1等價于a[j-left]=1,篩選時將所有a[left]~a[r]==a[0]~a[r-left] a[j-left]=1; } } int minn=INF,maxx=-1; int minflag=-1,minf=-1,minlast=-1,maxf=-1,maxlast=-1,pre=-1; for(LL i=left;i<=r;i++) { if(a[i-left]==0)//這裡一樣,也是用偏移index去判斷是否被篩出 { if(pre==-1) { pre=i; } else { if(i-pre<minn) { minf=pre; minlast=i; minn=i-pre; } if(i-pre>maxx) { maxf=pre; maxlast=i; maxx=i-pre; } pre=i; } //last=i; } } if(minf==-1) printf("There are no adjacent primes.\n"); else printf("%d,%d are closest, %d,%d are most distant.\n",minf,minlast,maxf,maxlast); } return 0; }
關於質數的一些重要結論:
設pi(n)為小於等於n的質數個數,則pi(n)\approxn/n/ln(n)
當n在10^5到10^6左右時,質數的數量大概可以用10/n來估計。
第 n 個質數大約是 nln(n)
《计算机算法导引: 设计与分析》有講到質數的這部分
另外一種求大範圍質數的方法:
http://www.jiancool.com/article/50042575894/
相关文章推荐
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#数据结构与算法揭秘二
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析
- C#常见算法面试题小结
- JavaScript 组件之旅(二)编码实现和算法
- PHP排序算法类实例