/*a254077.go计算序列oeis.org/a254077可能有用的标志参数包括:-num个=[20]尝试生成这么多术语。默认值20用于简单测试。-程序=[0]如果是肯定的,显示标准错误的进展。用于比较不同实现的性能。当学期数为倍数时,将报告进度。例如,如果指定了-prog=100000,每10万倍报告一次进展典型的进度报告可能如下所示a[200000]=204569:2.849688009s 1m35.221598503s显示第20万项的序列值计算最后100000项所用的时间总运行时间计算项[此程序的早期版本的总运行时间从工作开始,而不是时间计算术语。这将初始化与时间计算术语混为一谈。]-净空高度=[5]筛子Cbits用于记录哪些复合整数尚未出现在序列中。目前尚不清楚预测筛子大小的方法所有复合候选人都可以被审问。目前我们使用要求的条款数量(请参阅-num标志)乘以这个开销系数。它足以应付25亿个术语。过高估计可能会耗尽主内存。低估它将导致程序终止出现数组边界错误。-参见=[2003]对于小于或等于此的素数,请跟踪那个素数的最小倍数。对于减少重复跳过较小的倍数。-gcd1最大值=[无限]坚持gcd(a[n],a[n-1])不大于此值。-时间=[正确]根据标准错误报告主要时间和一些事件计数。例如,默认计算20个元素,你可能会看到为51103种元素制作筛子:604.755us发现20个元素:75.568us总运行时间:755.822us42个gcd()调用,17个错误顺序,103个循环,0个back2back最后一行的事件计数可能没什么意思除非您正在修改程序,但不会造成任何伤害。-研究=[错误]报告有关每个术语生成的相当详细的信息。这将使速度稍微减慢,并大大扩大输出。对于此程序的早期版本包括18 20:2^2*5:4>1:1:3^3:11:20:4:1:1:019 33:3*11:3>1:1:2^2*5:11:22:4:2:8:620 24:2^3*3:4>3:3:11p:11:22:121 11:11P:11>1:1:2^3*3:1:22:5:1:0:022 26:2*13:2>1:1:11p:13:22:5:1:3:223 22:2*11.11>2:2:13p:0:22:5:0:0……在字段4后进行拆分以避免过长的行9999571 10175857:1213*8389:1213>1:1:5*13^2*12041:5087323:10171703:354156:1:1079:30769999572 10174655:5*71*28661:5>1:1:1213*8389:5087323:10171703:354156:1:51:29029999573 10177070:2*5*839*1213:1213>5:5:71*28661:5087323:10171703:354156:2:2178:3190每行的n和a[n]后面有10个以冒号分隔的字段。为了简单起见,我们将参考gcd2=gcd(a[n],a[n-2])gcd1=gcd(a[n],a[n-1])这些字段包括:1) a的因子[n]。它们后面跟着一个“P”,当a[n]是素数时。2) gcd2>gcd13) gcd1的因素。4) a[n-1]/gcd1的因子。它们后面是一个“p”iff素数。5) 尚未见过的最小素数6) 尚未见到的最小组合7) 到目前为止看到的素数总数8) a[n]的候选素数9) 被视为a[n]候选的复合材料数量10) 跳过的复合候选数。一个候选者可能会被跳过,因为它实际上是一个素数,或者因为它是一种已经出现的复合物。关于上述术语的一些意见。对于n=21,字段9和10都是0。主要候选人结果证明,不到最小综合候选值是令人满意的。对于n=23,字段5和8均为0。因为a[n-2]是质数,没有其他素数可以有除1以外的gcd2,因此不考虑素数。对于n=9999573,字段9和10相当大。这是因为a[n-2]是两个大素数的乘积。综合候选人在生成输出的程序版本中按顺序搜索。我们遇到了许多(3190)候选人要么是最好的,要么是已经见过的,还有很多(2178)都是看不见的复合材料,只有最后一种是令人满意的。这一观察结果改变了合成候选人的方式已考虑。*/成套设备总管导入(“标志”“柔性制造技术”//“github.com/davecheney/profile”“数学”“操作系统”“时间”)var Huge int64=(1<<63)-1//大到64位int可以容纳var num=标志。Int64(“num”,20,“要报告的元素数”)var增长=标志。Int64(“增长”,1000,“没有候选人时增长”)var showtimes=标志。Bool(“时间”,true,“显示标准错误的处理时间”)var进度=标志。Int64(“prog”,0,“显示此进度的倍数”)var gcd1max=标志。Int64(“gcd1max”,巨大,“gcd1的最大值”)var净空=标志。Int64(“净空”,5,“复合材料筛的控制尺寸”)var研究=标志。Bool(“研究”,false,“显示有关术语的相当详细的信息”)var fseen=标志。Int64(“seento”,2003年,“通过这个减少跳过素数”)/*程序历史记录(如果有人计划修改):最初,我们在未使用的结构中只保留了一个“候选池”。据观察,水池中往往充满了看不见的素数。当合适的候选人是复合材料时(大多数情况下),在到达第一个之前,我们必须逐一检查所有的素数复合候选者。程序已更改,以维护单独的prime和Pool复合候选者,但仍处于未使用的结构中。这是一个保持主要候选人的机制非常令人满意,因为已经观察到(但尚未证明)素数按其作为整数出现的顺序添加到序列中。按顺序删除候选项,直到结构为空,然后补充。这不是一个令人满意的维护复合材料的机制候选人!当[n-2]是素数时,只有该素数的复合倍数可以显示为[n]。随着序列中出现越来越大的素数,按顺序遍历组合候选者,这是唯一的方法可用于未使用的结构,非常昂贵。对于一百万或更多的质数p,我们几乎访问了在遇到p的倍数之前,有许多复合候选人。复合池每增加*(1000)个新候选,可能会强制重新分配和复制池。通常(但尚未证明)已经看到2p,启用p的出现在后面两步,我们不知道直到我们达到3p。所以有很多每当我们遇到素数时,都会“挥舞”,这是可见的看着序列增长,每当素数为倒数第二学期。因此,对程序进行了修改,以将复合候选项保持为“筛子”,最初与用于识别底漆的筛子相同。虽然这让我们可以直接调查整数已被看到,按顺序访问以查找下一个正如上面的评论所讨论的,看不见的整数相当慢关于学习旗。所以我们“颠倒了重点”。而不是浏览看不见的候选人,寻找那些不是与a[n-2]互质,我们改为使用a[n-2]的因子来按顺序生成不能与[n-2]互素的整数,并用筛子来确定是否看不到它们。*///跟踪未使用的整数类型未使用的结构{下一个int64//根本没人见过seen[]int64//已看到但未使用最后一个int64//我们在seen中停止的位置zthru int64//seen中有多少前导0元素grow int64//填充时要添加多少新术语filter func(int64)bool//如果非空,则为新词条筛选}函数填充(u*未使用){如果u.filter==nil{对于len(美国){u.seen=附加(u.seen,u.next)联合国新闻++}返回}nxt:=u.next用于;nxt++{如果u.filter(nxt){u.seen=追加(u.seen,nxt)如果len(u.seen)==cap(u.seen){打破}}}u.next=nxt+1}func NewU(startAt,growBy int64,filter func(int64)bool)*未使用{u:=新(未使用)u.next=开始时间u.grow=增长依据u.filter=过滤器美国=制造商([]int64,0,u.grow)u.last=-1u.zthru=0填充(u)返回u}函数压缩(from,to*[]int64){对于_,i:=范围*从{如果i!=0个{*to=附加(*to,i)}}}函数增长(u*未使用){var大小int64=int64(cap(美国))+*增长较大:=品牌([]int64,0,size)挤压(美国,更大)u.zthru=0u.seed=更大u.last=int64(len(美国))-1填充(u)}功能重置(u*未使用){u.last=u.zthru-1}func saw(u*未使用){美国[u.last]=0}func next(u*未使用)int64{的{可能:=美元[u.last+1:大写(美元)]变量i int64=0对于_,n:=可能的范围{如果n!=0 {如果u.last+1==u.zthru{u.zthru+=i}最后一个+=i+1返回n}我++}增长(u)}}var素数[]int64//足够的素数来考虑我们可能看到的任何东西var Cbits[]int64//将候选组合成64位字函数因子(n int64)[][2]int64{因子:=make([][2]int64,0,10)对于_,p:=范围素数{如果p*p>n{打破}如果n%p==0{m:=整数64(1)n/=p对于n%p==0{n/=p米++}factors=追加(factors,[2]int64{p,m})}}如果n!=1 {factors=追加(factors,[2]int64{n,1})}收益率}函数isPrime(n int64)布尔{如果(n&1)==0{返回n=2}对于_,p:=范围素数[1:]{如果p*p>n{返回true}如果n%p==0{返回false}}return true//不应发生}函数是PrimeFact(因子[][2]int64)布尔{返回长度(因子)==1&&因子[0][1]==1}函数字位(索引int64)(字,位int64){位=1<<uint(索引&63)单词=索引>>6返回}函数isC(索引int64)布尔{word,bit:=wordBit(索引)return Cbits[word]和bit!=0}函数makeCand(索引int64){word,bit:=wordBit(索引)Cbits[word]|=位}函数清除C(索引int64){word,bit:=wordBit(索引)Cbits[word]&=^bit}func MakeNonPrimeSieve(n int64){//如果b是复合,则Cbits中的位b应为真,//而且还没有看到Cbits=制造([]int64,1+(n>>6))素数=make([]int64,0,int64(math.Log(float64(n)))n=64*int64(长度(Cbits))var x int64=2用于;x<n;x++(x++){如果!isC(x){素数=附加(素数,x)对于y:=2*x;y<n;y+=x{品牌C(y)}}}}func fS(factors[][2]int64)字符串{如果len(因子)<1{返回“1”}fs:=“”sep:=“”对于_,对:=范围因子{fs+=sepsep=“*”fs+=fmt。Sprintf(“%d”,对[0])如果对[1]>1{fs+=fmt。Sprintf(“^%d”,配对[1])}}返回fs}var GcdCalls int64=0var Gcd紊乱int64=0var GcdLoops int64=0//后面的大多数变量最初是main()的局部变量。//全局变量很难看,但重复的代码也是如此。//将重复的代码重构为子例程更容易//如果需要和可能修改的变量是全局变量。var n int64//序列中下一个元素的(基于0的)索引var Cbase int64=4//尚未看到的C位中的第一个索引var Cnext int64//尚未看到或拒绝的下一个C位索引//有关搜索下一个元素的信息,而非总计var Cskips int64//跳过了复合候选,因为看到了var Ccands int64//考虑复合候选var Pcands int64//考虑主要候选var back2、back1 int64//a[n-2]和a[n-1]var pback2,pback1 bool//是back2/back1质数var gcd2、gcd1 int64//gcd(k,back2)和gcd(k,back1)var u2 int64//back2/gcd1var gcd1not1 bool//是最后一个gcd1!=1,varpu2-bool//是u2-primevar pthis bool//是一个[n]素数var nxtP,nxtC int64//a[n]的下一个素数和复合候选var back2factors、back1factors和u2factors[][2]int64变量CstepSize int64var seeTo int64变量var CSeeTo[]int64/*人们推测,但尚未证明如果素数p没有出现并且a[n-2]是k*p那么p不除以a[n-1],那么a[n]就是p。这已通过2500000000个条款得到确认。我们统计所有不符合事实的情况。*/var备份P=0函数gcd(a,b int64)int64{Gcd呼叫++如果a<b{Gcd障碍++a、 b=b,a}对于b!=0 {Gcd环路++a、 b=b,a%b}返回a}类型advancer func()boolvar nextCfunc提前器函数fixedInit(){素数:=u2因子[0][0]CstepSize=素数//唯一可能的gcd是质数**i,i>=1//如果gcd1也有质数**k作为因子,//那么我们必须击败k作为一个因素。基线:=nxtCif prime<见To&&baseline<CSeeTo[prime]{基线=CSeeTo[prime]}普通:=gcd1对于公共%prime==0{公共/=素数CstepSize*=素数}nxtC=(基线+CstepSize-1)/CstepSizenxtC*=步长为了!isCand(nxtC){nxtC+=步长Cskips公司++}}func nextCfixed()bool{//nxtC始终是CstepSize的复合倍数。//进入时,nxtC无法满足gcd关系。//退出时,nxtC将是最不可见的复合倍数。//在真正退出时,nxtC小于nxtP。//在错误退出时,nxtC大于nxtP。nxtC+=步长为了!isC(nxtC){nxtC+=步长Cskips公司++}返回nxtC<nxtP}var因子列表[][2]int64函数fancyInit(){因子:=u2因子nf:=len(因子)FactorList=制造([][2]int64,nf)var第一个int64对于i:=0;i<nf;i++(i++){步长:=因子[i][0]//素因子FactorList[i][1]=步长如果stepSize<int64(len(CSeeTo)){first=CSeeTo[stepSize]}其他{第一个=(nxtC+stepSize-1)/步长first*=步长}为了!isC(第一个){first+=步长Cskips公司++}如果stepSize<int64(len(CSeeTo)){CSeeTo[stepSize]=第一个}FactorList[i][0]=第一个}nextCfancy()//将nxtC设置为最小倍数返回}func nextCfancy()bool{最小:=巨大至少:=-1对于i,NxtStepSize:=范围因子列表{nxt,步骤大小:=NxtStepSize[0],NxtStepSize[1]如果最小值>nxt{最小值=nxt至少t=i}else if least==nxt{nxt+=步长为了!isC(nxt){nxt+=步长Cskips公司++}因素列表[i][0]=nxt}}NxtStepSize:=因素列表[leastAt]nxt,步骤大小:=NxtStepSize[0],NxtStepSize[1]nxt+=步长为了!isC(nxt){nxt+=步长Cskips公司++}因素列表[leastAt][0]=nxtnxtC=最小值返回nxtC<nxtP}func checkC()bool{//在进入时,nxtC是迄今为止见过的最少的组合。//在真正退出时,nxtC是小于nxtP的合格组合。//在错误退出时,nxtC是大于nxtP的不可见复合。对于cLow:=true;c低;cLow=下一个Cfunc(){Cc和Cs++gcd2=gcd(背面2,nxtC)如果gcd2>1{gcd1=gcd(后1,nxtC)如果gcd2>gcd1&&gcd1<=*gcd1max{返回true}}}返回false}函数main(){//推迟配置文件。启动(profile.CPUProfile)。停止()标志。分析()开始:=时间。现在()progFirst:=开始progLast:=开始然后:=开始变量nxt,c1,p1 int64np:=*num如果np<*增长{np=*增长}np*=*净空如果int64(int(np))!=净现值{fmt公司。Fprintf(os.Stderr,“警告!int!=int64,结果不可靠\n”)}制造非原筛(np)请参阅收件人=*f请参阅如果看到To<19{seeTo=19//别傻了}如果seeTo>素数[len(素数)-1]{seeTo=素数[len(素数)-1]}请参阅To++//允许按质数直接索引CSeeTo=make([]int64,请参阅To)对于_,p:=范围素数{如果p<请参见收件人{CSeeTo[p]=2*p//p不是复合的}其他{打破}}如果*演出时间{fmt公司。打印f(os.Stderr,“为%d个元素制作筛子:%s\n”,np,时间。从那时起)then=时间。现在()}progAt:=*num+1如果*progress>0{progAt=*进度如果*进度<4{progAt=(4+*进度-1)/*进度progAt*=*进度}progFirst=时间。现在()progLast=progFirst}//报告前3个元素对于n=0;n<3;n++(n++){fmt公司。Fprintf(os.Stdout,“%d%d\n”,n+1,n+1)}素数Seen:=2//2和3pNums:=新U(n+1,*增长,函数(n int64)布尔{返回为Prime(n)})Cbase=n+1back2,pback2,back1,pback1=2,true,3,truegcd1not1,gcd1,u2,pu2=true,1,back2,trueback2因子、back1因子、u2因子=因子(back2)、因子(back 1)、因子对于n<*num{Pcd、Ccd、Cskips=0、0、0为了!isC(Cbase){Cbase数据库++Cskips公司++}Cnext=CbasenxtC=下一个c1=nxtC//考虑下一个主要候选人如果pback2{//所有其他素数的gcd==1nxtP=巨大p1=0}其他{//下一学期可能是黄金时段重置(pNums)nxtP=下一个(pNums)p1=nxtP}var maxFact int64=back2factors[len(back2factors)-1][0]如果len(u2factors)==1{//单一因素固定初始化()nextCfunc=下一个固定}其他{//真正的复合fancyInit()nextCfunc=下一个Cfant}的{用于;nxtP<nxtC;nxtP=下一个(pNums){如果nxtP>maxFact{nxtP=巨大打破}普坎迪斯++if(back2%nxtP)!=0 {//gcd为1,不合格持续}gcd2=nxtPif(back1%nxtP)==0{//两者都将nxtP作为一个共同因素//gcd2和gcd1相同//因此nxtP被拒绝后备2包++持续}gcd1=1nxt=nxtP锯(pNums)pthis=真转到报告}对于nxtC<nxtP{if检查C(){转到报表C}}}reportC://下学期报告复合nxt=nxtC清除C(nxt)pthis=错误报告:n个++如果n==编程At{progAt+=*进度fmt公司。打印f(os.Stderr,“a[%d]=%d:%s%s\n”,n、 nxt、,时间。自(progLast),时间。自(progFirst))progLast=时间。现在()}gcd1not1=(gcd1!=1)如果gcd1not1{u2=后退1/gcd1u2系数=系数(u2)pu2=基本事实(u2factors)}其他{u2=后1pu2=pback1u2factors=后1factors}如果pthis{素数Seen++}thisfactors:=系数(nxt)如果*研究{Pthis,Pu2:=“”,“”如果是pthis{Pthis=“P”}如果pu2{Pu2=“p”}fmt公司。打印f(os.Stdout,“%d%d:%s%s:%d>%d:%s:%s%s:%d:%d:%d:%d:%d:%d\n”,n、 nxt、,fS(本因子)、Pthis、gcd2、gcd1、,fS(因子(gcd1)),fS(u2因子),Pu2、p1、c1、,素数Seen、Pcands、Ccands、Cskips)}其他{fmt公司。Fprintf(os.Stdout,“%d%d\n”,n,nxt)}back2,pback2,back1,pback1=back1、pback1、nxt、pthisback2factors,back1factors=back1因子,thisfactors}如果*演出时间{fmt公司。Fprintf(os.Stderr,“正在查找%d个元素:%s\n”,*num,时间。自(progFirst))fmt公司。Fprintf(os.Stderr,“总运行时间:%s\n”,时间。自(开始)}fmt公司。打印f(os.Stderr,“%d个gcd()调用,%d个错误顺序,%d个循环,%d个back2back\n”,GcdCalls、GcdDisorder、GcdLoops、Back2backP)}