欧拉筛
这个狗日的欧拉筛真是慢到服气= =...
放一个uoj上1E的分解跑0.6s的欧拉筛.
#include<map>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<random>
#define pi 6000000
#define maxn 100000010
short low[maxn];
int pr[pi],prl;
inline int min(int a,int b){ return a<b?a:b; }
void sieve(int n=100000000,int i=6){
pr[0]=2; pr[1]=3; pr[2]=5; prl=3;
low[4]=2; low[6]=2; low[8]=2; low[9]=3;
low[10]=2; low[12]=2; low[14]=2; low[15]=3;
low[16]=2; low[25]=5;
for(int _=2000,v;i<=_;++i){
if(!(v=low[i])) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fket;
low[i*3]=3; if(3==v) goto fket;
low[i*5]=5; if(5==v) goto fket;
for(int j=3,t;j<prl && (t=i*pr[j])<=n;++j){
low[t]=pr[j];
if(v==pr[j]) goto fket;
} fket:;
}
for(int _=n/5,v;i<=_;++i){
if(!(v=low[i])) pr[prl++]=i,v=i;
low[i<<1]=2; if(!(i&1)) goto fk2;
low[i*3]=3; if(3==v) goto fk2;
low[i*5]=5; if(5==v) goto fk2;
v=min(v,n/i);
for(int j=3;pr[j]<=v && j<prl;++j) low[i*pr[j]]=pr[j];
fk2:;
}
for(int _=n/3;i+8<=_;){
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fk1;
low[i*3]=3; fk1:;
++i;
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fkb;
low[i*3]=3; fkb:;
++i;
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fkc;
low[i*3]=3; fkc:;
++i;
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fkd;
low[i*3]=3; fkd:;
++i;
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fke;
low[i*3]=3; fke:;
++i;
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fkf;
low[i*3]=3; fkf:;
++i;
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fkg;
low[i*3]=3; fkg:;
++i;
if(!low[i]) pr[prl++]=i;
low[i<<1]=2; if(!(i&1)) goto fkh;
low[i*3]=3; fkh:;
++i;
}
for(int _=n/3;i<=_;++i){
if(!low[i]) pr[prl++]=i;
low[i<<1]=2;
if(!(i&1)) goto fki;
low[i*3]=3;
fki:;
}
if(i&1){
if(!low[i]) pr[prl++]=i;
low[i<<1]=2;
++i;
}
for(int _=n>>1;i+8<=_;){
low[(i++)<<1]=2;
if(!low[i]) pr[prl++]=i;
low[(i++)<<1]=2;
low[(i++)<<1]=2;
if(!low[i]) pr[prl++]=i;
low[(i++)<<1]=2;
low[(i++)<<1]=2;
if(!low[i]) pr[prl++]=i;
low[(i++)<<1]=2;
low[(i++)<<1]=2;
if(!low[i]) pr[prl++]=i;
low[(i++)<<1]=2;
}
for(int _=n>>1;i<=_;++i){
if(!low[i]) pr[prl++]=i;
low[i<<1]=2;
}
while(i%3 || i&1){
if(!low[i]) pr[prl++]=i;
low[i<<1]=2;
++i;
}
for(int j=0;j<5;++j){
if(!low[i]) pr[prl++]=i;
low[i<<1]=2;
++i;
}
for(;i+120<=n;){
int a=i+2,b=i+6,c=i+8,d=i+12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
a+=12, b+=12, c+=12, d+=12;
if(!low[a]) pr[prl++]=a;
if(!low[b]) pr[prl++]=b;
if(!low[c]) pr[prl++]=c;
if(!low[d]) pr[prl++]=d;
i=d;
}
for(;i+24<=n;){
if(!low[i]) pr[prl++]=i; i+=2;
if(!low[i]) pr[prl++]=i; i+=4;
if(!low[i]) pr[prl++]=i; i+=2;
if(!low[i]) pr[prl++]=i; i+=4;
if(!low[i]) pr[prl++]=i; i+=2;
if(!low[i]) pr[prl++]=i; i+=4;
if(!low[i]) pr[prl++]=i; i+=2;
if(!low[i]) pr[prl++]=i; i+=4;
}
for(;i<=n;++i) if(!low[i]) pr[prl++]=i;
}
和咸鱼有什么区别= =..
当然我们可以加些特技!(坑待填)
Upd.1
改了改,用了wheel sieve的一些技巧.
(GitHub) https://github.com/iamstupid/codeBase/blob/master/OI/wheelSieve.cpp
(UOJ) http://uoj.ac/submission/68564
(达到了primesieve的1/5速度,可喜可贺)
(其实主要瓶颈在RAM吞吐上...毕竟每个low是一个short优化不了..)