线性筛素数(原来我之前学的不是线性的啊。。。
void getprime(){ rep(i,2,nmax){ if(!vis[i]) prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&i*prime[j]<=nmax;j++){ vis[i*prime[j]]=true; if(i%prime[j]==0) break; } } }
利用了每个合数必有一个最小素因子,每个合数仅被它的最小素因子筛去正好一次,所以是线性时间。
代码中体现在: if(i%prime[j]==0) break;(抄自M.J的blog
求欧拉函数
int getphi(int x){ int ans=x; for(int i=2;i*i<=x;i++){ if(x%i==0) ans=ans/i*(i-1); while(x%i==0) x/=i; } if(x!=1) ans=ans/x*(x-1); return ans; }
线性筛素数,欧拉函数。
欧拉函数性质:f(ab)=f(a)f(b);
void getphi(){ phi[1]=1; rep(i,2,nmax){ if(!vis[i]) prime[++prime[0]]=i,phi[i]=i-1; rep(j,1,prime[0]) { int x=prime[j]; if(i*x>nmax) break; vis[i*x]=true; if(i%x==0){ phi[i*x]=phi[i]*x;break; }else phi[i*x]=phi[i]*phi[x]; } } }
poj2407:求欧拉函数
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset(x,c,sizeof(x)) int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } int getphi(int x){ int ans=x; for(int i=2;i*i<=x;i++){ if(x%i==0) ans=ans/i*(i-1); while(x%i==0) x/=i; } if(x!=1) ans=ans/x*(x-1); return ans; } int main(){ //rep(i,2,100) printf("%d:%d ",i,getphi(i)); while(1){ int n=read(); if(!n) break; printf("%d ",getphi(n)); } return 0; }
poj2478:求欧拉函数前缀和
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define clr(x,c) memset(x,c,sizeof(x)) #define ll long long int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1000005; int prime[nmax],phi[nmax]; bool vis[nmax]; void getphi(){ phi[1]=1; rep(i,2,nmax){ if(!vis[i]) prime[++prime[0]]=i,phi[i]=i-1; rep(j,1,prime[0]) { int x=prime[j]; if(i*x>nmax) break; vis[i*x]=true; if(i%x==0){ phi[i*x]=phi[i]*x;break; }else phi[i*x]=phi[i]*phi[x]; } } } int main(){ getphi(); //rep(i,1,100) printf("%d:%d ",i,phi[i]);printf(" "); while(1){ int n=read(); if(!n) break; ll ans=0; rep(i,2,n) ans+=phi[i]; printf("%lld ",ans); } return 0; }