O(n) 筛选素数
#include<bits/stdc++.h> using namespace std; const int M = 1e6 + 10 ; int mindiv[M] ;//每个数的最小质因数 int prim[M] , pnum ;//存素数 bool vis[M] ; void prim () { for (int i = 2 ; i < M ; i ++) { if (!vis[i]) { mindiv[i] = i ; prim[ pnum++ ] = i ; } for (int j = 0 ; j < pnum ; j ++) { if ( i*prim[j] >= M ) break ; vis[ i*prim[j] ] = 1 ; mindiv[i] = prim[j] ; if (i % prim[j] == 0) break ; } } } int main () { prim () ; return 0 ; }
欧拉函数:phi[i] 为<= i 的范围内与i互质的数的数量
欧拉埃筛,写起来简单,复杂度O(log(log(N)))(zstu 幻神):
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int M = 1e6 + 10 ; int n, m, T; int euler[M]; void Euler () { for(int i = 0; i < M ; i ++) euler[i] = i; for(int i = 2; i < M ; i ++){ if(euler[i] == i) { for (int j = i; j < M ; j += i) { euler[j] = euler[j] - euler[j]/i; } } } } int main(){ Euler (); int n ; while (~ scanf ("%d" , &n)) printf ("%d " , euler[n]) ; return 0; }
欧拉线筛,写起来复杂点,(墨迹了我半天)复杂度O(N):
#include<bits/stdc++.h> using namespace std; const int M = 1e6 + 10 ; int prim[M] , pnum ; bool vis[M] ; int phi[M] ; void Euler () { for (int i = 2 ; i < M ; i ++) { if (!vis[i]) { prim[ pnum++ ] = i ; phi[i] = i - 1; } for (int j = 0 ; j < pnum ; j ++) { int x = i * prim[j] ; if (x >= M ) break ; vis[x] = 1 ; if (i % prim[j] == 0) { int y = i , cnt = 0 , z = prim[j] ; while (y % prim[j] == 0) cnt ++ , y /= prim[j] , z *= prim[j] ; if (y == 1) phi[x] = x - x/prim[j] ; else phi[x] = phi[y] * phi[z] ; break ; } else phi[x] = phi[i] * phi[ prim[j] ] ; } } } int main () { Euler () ; int n ; while (~ scanf ("%d" , &n)) printf ("%d " , phi[n]) ; return 0 ; }
线性欧拉跟新:
#include<cstdio> #include<iostream> using namespace std; int prime[100005],phi[1000005]; int main(){ int i,j; for(i=2;i<1000002;++i){ if(!phi[i]){ phi[i]=i-1; prime[++prime[0]]=i; } for(j=1;j<=prime[0]&&(long long)i*prime[j]<1000002;++j) if(i%prime[j])phi[i*prime[j]]=phi[i]*(prime[j]-1); else{ phi[i*prime[j]]=phi[i]*prime[j]; break; } } int T,n; scanf("%d",&T); while(T--){ scanf("%d",&n); printf("%d ",phi[n+1]); } }