线性筛-euler,强大O(n)
Posted Jason-Cow
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线性筛-euler,强大O(n)相关的知识,希望对你有一定的参考价值。
欧拉函数是少于或等于n的数中与n互质的数的数目
φ(1)=1(定义)
类似与莫比乌斯函数,基于欧拉函数的积性
φ(xy)=φ(x)φ(y)
由唯一分解定理展开显然,得证
精髓在于对于积性的应用:
if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;} phi[i*p[j]]=phi[i]*(p[j]-1);
一个练手题Hdu1286
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <cmath> 8 #include <queue> 9 #include <map> 10 #include <set> 11 using namespace std; 12 #define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout) 13 inline void read(int &ans){ 14 ans=0;char x=getchar();int f=0; 15 while(x<\'0\'||x>\'9\'){if(x==\'-\')f=1;x=getchar();} 16 while(x>=\'0\'&&x<=\'9\')ans=ans*10+x-\'0\',x=getchar(); 17 if(f)ans=-ans; 18 } 19 20 const int maxn=50000+10; 21 int phi[maxn],p[maxn],flag[maxn],cnt; 22 void euler(int n){ 23 phi[1]=1; 24 for(int i=2;i<=n;i++){ 25 if(!flag[i])p[++cnt]=i,phi[i]=i-1; 26 for(int j=1;j<=cnt && i*p[j]<=n;j++){ 27 flag[i*p[j]]=1; 28 if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;} 29 phi[i*p[j]]=phi[i]*(p[j]-1); 30 } 31 } 32 } 33 34 int main(){ 35 euler(32768); 36 int CN,N; 37 for(read(CN);CN--;)read(N),printf("%d\\n",phi[N]); 38 return 0; 39 }
Hdu1787线性筛O(n),MLE,怎么办?在线算
1 int euler(int n){ 2 int ans=n; 3 for(int i=2;i*i<=n;i++){ 4 if(n%i==0)n/=i,ans-=ans/i; 5 while(n%i==0)n/=i; 6 } 7 if(n>1)ans-=ans/n; 8 return ans; 9 }
AC code:
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <cmath> 8 #include <queue> 9 #include <map> 10 #include <set> 11 using namespace std; 12 #define file(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout) 13 inline bool read(int &ans){ 14 ans=0;char x=getchar();int f=0; 15 while(x<\'0\'||x>\'9\'){if(x==\'-\')f=1;x=getchar();} 16 while(x>=\'0\'&&x<=\'9\')ans=ans*10+x-\'0\',x=getchar(); 17 if(f)ans=-ans; 18 return !!ans; 19 } 20 /* 21 const int maxn=(int)1e8+10; 22 int phi[maxn],p[maxn],flag[maxn],cnt; 23 void euler(int n){ 24 phi[1]=1; 25 for(int i=2;i<=n;i++){ 26 if(!flag[i])p[++cnt]=i,phi[i]=i-1; 27 for(int j=1;j<=cnt && i*p[j]<=n;j++){ 28 flag[i*p[j]]=1; 29 if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;} 30 phi[i*p[j]]=phi[i]*(p[j]-1); 31 } 32 } 33 } 34 */ 35 36 int euler(int n){ 37 int ans=n; 38 for(int i=2;i*i<=n;i++){ 39 if(n%i==0)n/=i,ans-=ans/i; 40 while(n%i==0)n/=i; 41 } 42 if(n>1)ans-=ans/n; 43 return ans; 44 } 45 46 int main(){ 47 //euler((int)1e8);cout<<euler(1)<<endl; 48 for(int N;read(N);)printf("%d\\n",N-euler(N)-1); 49 return 0; 50 }
Hdu2824,sigma(a,b) phi(x)
1 #include <algorithm> 2 #include <iostream> 3 #include <cstring> 4 #include <cstdlib> 5 #include <cstdio> 6 #include <vector> 7 #include <cmath> 8 #include <queue> 9 #include <map> 10 #include <set> 11 using namespace std; 12 13 typedef long long ll; 14 const int maxn=(int)3e6+10; 15 ll phi[maxn];int p[maxn],cnt;bool flag[maxn]; 16 void euler(int n){ 17 phi[1]=1; 18 for(int i=2;i<=n;i++){ 19 if(!flag[i])p[++cnt]=i,phi[i]=i-1; 20 for(int j=1;j<=cnt && i*p[j]<=n;j++){ 21 flag[i*p[j]]=1; 22 if(i%p[j]==0){phi[i*p[j]]=phi[i]*p[j];break;} 23 phi[i*p[j]]=phi[i]*(p[j]-1); 24 } 25 } 26 for(int i=1;i<=n;i++)phi[i]+=phi[i-1]; 27 } 28 29 int main(){ 30 euler((int)3e6); 31 for(int a,b;scanf("%d%d",&a,&b)==2;)printf("%lld\\n",phi[b]-phi[a-1]); 32 return 0; 33 }
以上是关于线性筛-euler,强大O(n)的主要内容,如果未能解决你的问题,请参考以下文章