总目录

在线测评地址(ybt)   只有1个测试点

在线测评地址(POJ)   无法提交

在线测评地址(LOJ)   只有1个测试点

在线测评地址(LUOGU)   要有UVA账号才能提交

1.0分代码,使用了位置与数值,数值与位置的映射关系,确定了数的左最近质数,右最近质数。

ybt

未通过

测试点 结果 内存 时间
测试点1 运行错误 159432KB 130MS

LOJ

看完题,马上跳出 线性筛,但看看数据范围1<=L< U<=2,147,483,647,即2.1*10^9,明显超时,似乎要从RL≤10^6突破,目前没什么感觉的情况下,先编个线性筛,在1-100区间,用25个质数,找找规律,再拓展到10^7找找规律,先找规律,再图突破2.1*10^9,当然肯定有技巧的,看看能否触碰到技巧,若不行,再学习 提高+/省选- 的技巧,也是蛮好。

线性筛代码如下:

#include <bits/stdc++.h>
#define maxn 10000010
using namespace std;
int prime[maxn],tot=0,b[maxn];
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1;if(i%prime[j]==0)break;}}
}
int main(){int n,i;scanf("%d",&n);linear(n);for(i=1;i<=tot;i++)printf("%d ",prime[i]);return 0;
}

对应100以内的输入输出数据如下:

100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

100以内25个质数间距

(2 3)间距1
(3 5)间距2
(5 7)间距2
(7 11)间距4
(11 13)间距2
(13 17)间距4
(17 19)间距2
(19 23)间距2
(23 29)间距2
(29 31)间距2
(31 37)间距6
(37 41)间距4
(41 43)间距2
(43 47)间距4
(47 53)间距7
(53 59)间距6
(59 61)间距2
(61 67)间距6
(67 71)间距4
(71 73)间距2
(73 79)间距6
(79 83)间距4
(83 89)间距6
(89 97)间距8

找规律的同时,打表应该也是好办法,猜测该题,肯定是将2^31范围内的质数打出,进行研究,进而出了该题,也一直好奇2^31范围内的质数有多少呢,2^31=2.1*10^9,猜测应该在10^7个以内,打出来看看。

尝试了打表,发现数组开不了2,147,483,647这么大。

重心放在找规律上。

#include <bits/stdc++.h>
#define maxn 10000010
using namespace std;
int prime[maxn],tot=0,b[maxn],pos[maxn],left[maxn],right[maxn];
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i,pos[i]=tot;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1;if(i%prime[j]==0)break;}}
}
int main(){int n,i,a,b;linear(10000000);while(scanf("%d%d",&a,&b)!=EOF){}return 0;
}

目前情况,将10^7以内的情况编出,感觉还是不容易,先编出,再说。

统计了10^7以内的质数数量,有664579个,统计代码如下:

#include <bits/stdc++.h>
#define maxn 10000010
using namespace std;
int prime[maxn],tot=0,b[maxn],pos[maxn],left[maxn],right[maxn];
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i,pos[i]=tot;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1;if(i%prime[j]==0)break;}}
}
int main(){int n,i,a,b;linear(10000000);printf("tot=%d\n",tot); return 0;
}

对应的输入输出数据如下:

tot=664579

按枚举的方式,10^7以内的最近,最远,距离应该可以编出。

打算标记10^7以内的数的左边最靠近的质数,右边最靠近的质数,如下

left[2]=2,right[2]=2
left[3]=3,right[3]=3
left[4]=3,right[4]=5
left[5]=5,right[5]=5
left[6]=5,right[6]=7

这样统计,比较方便的能确定靠近某个数的质数。

样例通过的0分代码如下:

#include <bits/stdc++.h>
#define maxn 10000010
using namespace std;
int prime[maxn],tot=0,b[maxn],pos[maxn],lt[maxn],rt[maxn];
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i,pos[i]=tot;//pos[i]=tot确定质数i与位次tot的映射关系 for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1;if(i%prime[j]==0)break;}}
}
int main(){int n,i,j,a,b,mn,mx,c,d1,d2,d3,d4;linear(10000000);rt[1]=2;for(i=2;i<=tot;i++){lt[prime[i-1]]=rt[prime[i-1]]=prime[i-1];//质数的左近,右近质数是自己本身 lt[prime[i]]=rt[prime[i]]=prime[i]; for(j=prime[i-1]+1;j<=prime[i]-1;j++)lt[j]=prime[i-1],rt[j]=prime[i];//数j左最近质数lt[j],右最近质数rt[j]}while(scanf("%d%d",&a,&b)!=EOF){if(rt[a]>=lt[b])printf("There are no adjacent primes.\n");else{mn=10000010,mx=0;for(i=pos[rt[a]];i<pos[lt[b]];i++){c=prime[i+1]-prime[i];if(c<mn)mn=c,d1=prime[i],d2=prime[i+1];if(c>mx)mx=c,d3=prime[i],d4=prime[i+1];}printf("%d,%d are closest, %d,%d are most distant.\n",d1,d2,d3,d4);  } }return 0;
}

2.筛出区间内质数,运行超时代码0分

ybt

未通过

测试点 结果 内存 时间
测试点1 运行超时 13756KB 999MS

LOJ

突破口猜测还是在R−L≤10^6

突然想到,该题的关键还是快速筛出给定区间[L,R]内的所有质数,有办法吗?

要筛出2,147,483,647是否是质数,只需检查能否被[1,sqrt(2,147,483,647)](即[1,46341])区间内的某个质数整除,

[1,46341]区间内的质数个数,

统计质数数量代码如下:

#include <bits/stdc++.h>
#define maxn 10000010
using namespace std;
int prime[maxn],tot=0,b[maxn];
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1;if(i%prime[j]==0)break;}}
}
int main(){int n;scanf("%d",&n); linear(n);printf("tot=%d\n",tot); return 0;
}

对应的输入输出数据如下:

46341
tot=4792

R-L=10^6的极端条件下,极端计算次数10^6*4792=4.8*10^9,在没有好办法的情况下,可以一试。计算过程中,适当使用long long,避免数据溢出。

除了2以外的质数,都是奇数,自然数由奇数和偶数构成,那么R-L=10^6的极端条件下,极端计算次数,只考虑奇数的情况下,10^6*4792/2=2.4*10^9

准备尝试计算[2147483647-10^6+1,2147483647],即计算区间[2146483648,2147483647]内的奇数(假定这些奇数全是质数),需要判定这些奇数全是质数的计算次数。

sqrt(2146483649)=46331,sqrt(2147483647)=46341,[1,46341]区间内的质数个数4792,计算次数接近10^6*4792/2=2.4*10^9,那真实计算次数,是多少,那就编码来体验吧。

#include <bits/stdc++.h>
#define maxn 10000010
#define LL long long
using namespace std;
int prime[maxn],tot=0,b[maxn];
LL cnt=0;
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1;if(i%prime[j]==0)break;}}
}
int main(){int n,j,a,b,mn,mx,c,d1,d2,d3,d4;LL i;linear(46341);//46341=sqrt(2147483647) //[2146483648,2147483647]for(i=2146483649;i<=2147483647;i+=2)for(j=1;j<=tot&&(LL)prime[j]*prime[j]<=2147483647;j++){cnt++;if(i%prime[j]==0)break;}printf("cnt=%lld\n",cnt);return 0;
}

上述编码对应的输入输出数据如下:

cnt=273481050

2.7*10^8超时无疑,试着编编吧。

同时准备上STL map容器,避免质数,合数的重复查找,以应对多组测试数据。

样例通过,筛出区间内质数,运行超时代码0分 如下:

#include <bits/stdc++.h>
#define maxn 1000010
#define LL long long
using namespace std;
int prime[maxn],tot=0,b[maxn],p[maxn],pn=0;//p[]记录区间内的质数
map<int,int> mp;
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i,mp[i]=1;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1,mp[prime[j]*i]=2;if(i%prime[j]==0)break;}}
}
int main(){int n,j,lt,rt,first,second,mn,mx,c,d1,d2,d3,d4;LL i;linear(46341);//46341=sqrt(2147483647) while(scanf("%d%d",&lt,&rt)!=EOF){pn=0;if(lt<=2)p[++pn]=2,lt=3;if(lt%2==0)lt+=1;//让lt变成奇数 if(rt%2==0)rt-=1;//让rt变成奇数for(i=lt;i<=rt;i+=2){//筛出[lt,rt]之间的质数 if(mp[i]==0){for(j=1;j<=tot&&(LL)prime[j]*prime[j]<=i;j++)if(i%prime[j]==0)break;if(i%prime[j]==0)mp[i]=2;//i是合数 else mp[i]=1,p[++pn]=i;//i是质数 }else if(mp[i]==1)p[++pn]=i;}if(pn<2)printf("There are no adjacent primes.\n");else{mn=1000010,mx=0;for(j=1;j<pn;j++){c=prime[j+1]-prime[j];if(c<mn)mn=c,d1=prime[j],d2=prime[j+1];if(c>mx)mx=c,d3=prime[j],d4=prime[j+1];}printf("%d,%d are closest, %d,%d are most distant.\n",d1,d2,d3,d4);} }return 0;
}

3.求任意区间质数的筛子100分

ybt

通过

测试点 结果 内存 时间
测试点1 答案正确 50304KB 927MS

LOJ

以[51,100]区间内找质数,演示求任意区间质数的筛子

找出[51,100]区间内的质数,
需要准备的质数范围[1,sqrt(100)],即[1,10],
该区间的质数是2,3,5,7可用普通的线性筛获得,
[51,100]内的合数,只会包含2,3,5,7这4个质因数,目标,找出[51,100]内的所有合数,那么剩下的就是质数了。针对质因数2,
[51/2,100/2]对应区间[25,50],制造出合数
25*2=50,26*2=52,27*2=54,28*2=56,29*2=58,30*2=60,31*2=62,32*2=64,33*2=66,
34*2=68,35*2=70,36*2=72,37*2=74,38*2=76,39*2=78,40*2=80,41*2=82,42*2=84,
43*2=86,44*2=88,45*2=90,46*2=92,47*2=94,48*2=96,49*2=98,50*2=100针对质因数3,
[51/3,100/3]对应区间[17,33],制造出合数
17*3=51,18*3=54,19*3=57,20*3=60,21*3=63,22*3=66,23*3=63, 24*3=72, 25*3=75,
26*3=78, 27*3=81, 28*3=84, 29*3=87, 30*3=90, 31*3=93, 32*3=96, 33*3=99针对质因数5,
[51/5,100/5]对应区间[10,20],制造出合数
10*5=50, 11*5=55, 12*5=60, 13*5=65, 14*5=70, 15*5=75, 16*5=80, 17*5=85, 18*5=90,
19*5=95, 20*5=100针对质因数7,
[51/7,100/7]对应区间[7,14],制造出合数
7*7=49, 8*7=56, 9*7=63, 10*7=70, 11*7=77, 12*7=84, 13*7=91, 14*7=98[51,100]之间的数 ()内的数,表示将其筛出的质因数
51(3) 52(2) 53 54(2,3) 55(5) 56(2) 57(3) 58(2) 59
60(2,3) 61 62(2) 63(3) 64(2) 65(5) 66(2,3) 67 68(2) 69(3)
70(2,5) 71 72(2,3) 73 74(2) 75(5) 76(2) 77(7) 78(2,3) 79
80(2,5) 81(3) 82(2) 83 84(2,7) 85(5) 86(2) 87(3) 88(2) 89 90(2,3,5)
91 92(2) 93(3) 94(2) 95(5) 96(2,3) 97 98(2) 99(3) 100(5)除了合数,剩下的就是质数了
53 59 61 67 71 73 79 83 89 91 97

目前为止,意识到了,编程世界里,乘法(3.求任意区间质数的筛子100分)比除法(2.筛出区间内质数,运行超时代码0分)好

还是引入STL map容器,对应较大数据(开数组要爆内存),

提供一组边界样例

输入:
1 2输出:
There are no adjacent primes.

求任意区间质数的筛子100分 代码如下:

#include <bits/stdc++.h>
#define maxn 1000010
#define LL long long
using namespace std;
int prime[maxn],tot=0,b[maxn],p[maxn],pn=0;//p[]记录区间内的质数
map<int,int> mp;
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1,mp[prime[j]*i]=2;if(i%prime[j]==0)break;}}
}
int main(){int n,j,lt,rt,first,second,mn,mx,c,d1,d2,d3,d4;LL i;linear(46341);//46341=sqrt(2147483647) while(scanf("%d%d",&lt,&rt)!=EOF){pn=0;if(lt<2)lt=2;//左边界处理 for(i=1;i<=tot&&(LL)prime[i]*prime[i]<=rt;i++)for(j=lt/prime[i];j<=rt/prime[i];j++)if(j>1)mp[j*prime[i]]=2;//=2表示该数是合数 for(i=lt;i<=rt;i++)if(mp[i]==0)p[++pn]=i;if(pn<2)printf("There are no adjacent primes.\n");else{mn=1000010,mx=0;for(j=1;j<pn;j++){c=p[j+1]-p[j];if(c<mn)mn=c,d1=p[j],d2=p[j+1];if(c>mx)mx=c,d3=p[j],d4=p[j+1];}printf("%d,%d are closest, %d,%d are most distant.\n",d1,d2,d3,d4);} }return 0;
}

比较好奇,极端条件下的计算次数,编码如下:

准备尝试计算[2147483647-10^6+1,2147483647],即计算区间[2146483648,2147483647]内的计算次数

#include <bits/stdc++.h>
#define maxn 1000010
#define LL long long
using namespace std;
int prime[maxn],tot=0,b[maxn],p[maxn],pn=0;//p[]记录区间内的质数
map<int,int> mp;
void linear(int x){int i,j;for(i=2;i<=x;i++)b[i]=0;for(i=2;i<=x;i++){if(b[i]==0)prime[++tot]=i;for(j=1;j<=tot&&prime[j]*i<=x;j++){b[prime[j]*i]=1,mp[prime[j]*i]=2;if(i%prime[j]==0)break;}}
}
int main(){int n,j,lt,rt,first,second,mn,mx,c,d1,d2,d3,d4;LL i,cnt=0;linear(46341);//46341=sqrt(2147483647) scanf("%d%d",&lt,&rt);for(i=1;i<=tot&&(LL)prime[i]*prime[i]<=rt;i++)cnt+=(rt-lt+1)/prime[i];printf("cnt=%lld\n",cnt);return 0;
}

上述代码对应的输入输出数据如下:

2146483648 2147483647
cnt=2633780

计算次数2.6*10^6断定极端条件下的测试数据,不会超过10组。

提高+/省选- 教会我什么? 线性筛不要固化,可以拓展拓展,求某一区间的合数,进而求得质数。

1619 例题 Prime Distance(POJ2689 LOJ10197 UVA10140 提高+/省选-) 线性筛 映射关系 0分 筛出区间内质数 超时0分 求任意区间质数的筛子100分相关推荐

  1. UVA10140 Prime Distance

    UVA10140 Prime Distance 给定两个整数L,R(1<=L<=R<=2^{31},R-L<=10^6)L,R(1<=L<=R<=231,R− ...

  2. 解题报告:poj2689 Prime Distance

    2017-10-03 11:29:20 writer:pprp 来源:kuangbin模板 从已经筛选好的素数中筛选出规定区间的素数 /* *prime DIstance *给出一个区间[L,U],找 ...

  3. Prime Distance On Tree-树分治+FFT

    题目描述 Problem description. You are given a tree. If we select 2 distinct nodes uniformly at random, w ...

  4. 1624 Violet 5 樱花(Bzoj2721 LOJ10202 LUOGU1445 提高+/省选-) 交叉相乘 阶乘质因数分解技巧 约数个数计算

    总目录 在线测评地址(ybt) 在线测评地址(LOJ) 在线测评地址(LUOGU) 1.交叉相乘 阶乘质因数分解技巧 约数个数计算 ybt 通过 测试点 结果 内存 时间 测试点1 答案正确 604K ...

  5. 弘辽科技:拼多多新店dsr分多久出?如何提高?

    对拼多多新店的卖家来说,需要去做好店铺的dsr评分,但是不少人的拼多多商家们都不清楚拼多多新店DSR分多久出,为了解决大家的问题,下面的内容中为大家进行介绍哦. 拼多多新店DSR评分多久出? 拼多多D ...

  6. SQLserver----对成绩表、笔试成绩提高5分 100分封顶

    语法 update table   set 字段1=case          when 条件1 then 值1            when 条件2 then 值2           else  ...

  7. Prime Distance POJ - 2689 线性筛

    一个数 $n$ 必有一个不超过 $\sqrt n$ 的质因子. 打表处理出 $1$ 到 $\sqrt n$ 的质因子后去筛掉属于 $L$ 到 $R$ 区间的素数即可. Code: #include&l ...

  8. POJ - 2689 Prime Distance(素数区间筛模板)

    题目链接:点击查看 题目大意:给出一段闭区间[l,r],求区间内相邻距离最大的素数对和相邻距离最小的素数对,题目保证r-l<=1e6,1<=l<=r<= 题目分析:因为我们要求 ...

  9. uva 10140——Prime Distance

    题意:题目出的很简单,给定一个数据范围(好吧,又是给定一个范围),然后问你在这个给定的范围内,哪两个相邻素数挨的最近,哪两个最远. 思路:这破题数据量很大,如果直接打表,铁定T,我蛋疼地打过两边了,T ...

最新文章

  1. php 清除缓存的操作,PHP清除缓存的几种方法
  2. mysql 日志文件mysql-bin文件清除方法,和mysql-bin相关文件的配置
  3. **PCD数据获取:Kinect+OpenNI+PCL对接(代码)
  4. 8. Action过滤
  5. [密码学基础][每个信息安全博士生应该知道的52件事][Bristol Cryptography][第17篇]述和比较DES和AES的轮结构
  6. 面试题40. 最小的k个数
  7. 锋神教我数据库,吴大哥教我写文档——其一
  8. Spark Streaming 原理剖析
  9. 练习:《斗鱼视频》m3u8流视频采集下载+思路+Python
  10. hping3 应用笔记
  11. RSD的遥感图像合成工具
  12. 基于MIMO讲解信道估计基本原理
  13. 技术人的未来(一)——跳槽
  14. html实现波浪,纯CSS实现波浪移动效果的示例
  15. HTTP1.1协议-RFC2616-中文版
  16. [每天一个Linux小技巧] Goldendict 快速取词
  17. Python的excel操作——PasteSpecial实现选择性粘贴自动化
  18. opencv 学习笔记(七) 灰度变换
  19. 彩铅练习,夜色中的小鸟
  20. Nature Cell Biology:揭示 PI3K-Akt 信号通路新机制,有望成为癌症治疗新靶点

热门文章

  1. windows操作系统序列号大全(经典之作)
  2. UltraEdit的注册码,版本:15.10.0.1026
  3. Unity Hair 毛发系统 初体验
  4. C语言中变量的作用域和生命周期
  5. 华师大计算机学院院士,华师大新建4大学院1个研究院顺应AI发展
  6. MyBatis学习笔记(1)—使用篇
  7. qq文件怎么传到百度云_如何将手机百度网盘中的文件发送给微信或qq好友 看完就明白了...
  8. Ubuntu22.04上安装Xilinix Vivado 2018.3
  9. 星露谷物语联机服务器位置已满,星露谷物语联机版
  10. iOS MJRefresh 自定义刷新动画