牛逼的线性时间筛法
这个牛B的筛法是在这里看到的
复杂度是线性的,扩展性超好~
自己YY了几个可以扩展的内容,权当模板~
#define N 1024 //niubee linear sevie method int phi[N],//欧拉函数 p[N],//素数表 ld[N],//最小素因子 ldt[N],//最小素因子的次数 min_pk[N],//if p==ld[n],min_pk[n]=1+p+p^2+...+p^ldt[n]; sig[N],//约数和 nd[N];//因子数 //依赖性:min_pk<-sig;ldt<-nd; void sevie() { memset(p,0,sizeof(p)); int i,j; phi[0]=0;phi[1]=1;//phi ld[0]=0;ld[1]=1;//ld ldt[0]=0;ldt[1]=1;//ldt min_pk[0]=0;min_pk[1]=1;//min_pk sig[0]=0;sig[1]=1;//sig nd[0]=0;nd[1]=1;//nd for(i=2;i<=N;i++) { if(!p[i]){ p[++p[0]]=i; phi[i]=i-1; ld[i]=i; ldt[i]=1; min_pk[i]=i+1; sig[i]=i+1; nd[i]=2; } for(j=1;p[j]<=N/i;j++) { p[p[j]*i]=1; ld[p[j]*i]=p[j]; if(i%p[j]){ phi[p[j]*i]=phi[p[j]]*phi[i]; ldt[p[j]*i]=1; min_pk[p[j]*i]=p[j]+1; sig[p[j]*i]=sig[i]*sig[p[j]]; nd[p[j]*i]=nd[p[j]]*nd[i]; } else{ phi[p[j]*i]=phi[i]*p[j]; ldt[p[j]*i]=ldt[i]+1; min_pk[p[j]*i]=p[j]*min_pk[i]+1; sig[p[j]*i]=sig[i]/min_pk[i]*min_pk[p[j]*i]; nd[p[j]*i]=nd[i]/(ldt[i]+1)*(ldt[p[j]*i]+1); break; } } } }
poj1811,权当模板~
#include <stdio.h> #include <string.h> #include <stdlib.h> #define swap(a,b) do{a=a^b;b=a^b;a=a^b;}while(0) typedef long long LL; LL gcd(LL a,LL b) { while(b){swap(a,b);b=b%a;} return a>0?a:-a; } LL mod_mult(LL a,LL b,LL mo)//ret:a*b%mo { LL ret; a%=mo; for(ret=0;b;a=(a<<1)%mo,b>>=1) if(b&1) ret=(ret+a)%mo; return ret; } LL mod_exp(LL a,LL b,LL mo)//ret:a^b%mo { LL ret=1,temp=a%mo; for(;b;b>>=1,temp=mod_mult(temp,temp,mo)) if(b&1) ret=mod_mult(ret,temp,mo); return ret; } LL pollard_rho(LL n,int c) { LL x,y,d,i=1,k=2; x=rand()%(n-1)+1; y=x; while(1) { i++; x=(mod_mult(x,x,n)+c)%n; d=gcd(y-x,n); if(d>1&&d<n)return d; if(x==y)return n; if(i==k)y=x,k<<=1; //if(k>1<<11)return n; } } int miller_rabin(LL n,int time) { if (n==2||n==3||n==5||n==7)return 1; if (n<2||!(n&1))return 0; int i,j,t=0; LL a,x,y,u=n-1; while((u&1)==0) t++,u>>=1; for(i=0;i<time;i++) { a=rand()%(n-1)+1; x=mod_exp(a,u,n); for(j=0;j<t;j++) { y=mod_mult(x,x,n); if (y==1&&x!=1&&x!=n-1) return 0; x=y; } if (x!=1) return 0; } return 1; } LL min; void fuck(LL i) { LL x; if(miller_rabin(i,8)){if(i<min)min=i;/*printf(" %lld ",i);*/return;} do{x=pollard_rho(i,rand()%15+2);}while((x==1||x==i)); fuck(x); fuck(i/x); } int main() { LL i;int t; scanf("%d",&t); while(t--){ scanf("%lld",&i); min=i; fuck(i); if(i!=min)printf("%lld\n",min); else printf("Prime\n");} return 0; }