$\ \ \ \ \ \ \ \,$利用线性欧拉筛筛选常见积性函数的模板总结:
- 用欧拉筛法线性筛素数
$\ \ \ \ \ \,$我们知道,若$x$为素数的话,那么必然若有任意一个不为$1$的数$a$,$(a\cdot x)$不是素数,打上标记。
$\ \ \ \ \ \,$并且必然有$a<a\cdot x$,$x<a\cdot x$,所以我们不断枚举$a$,在之前若是没有被打上标记,那么$a$就是素数。再不断枚举之前筛出来的素数$x$,对范围$[a,n]$中的$(a\cdot x)$打上标记。
$\ \ \ \ \ \,$若是当前$a$已经是某一个$x$的倍数,那么我们便可不必向后枚举$x$了,因为后面的$(a\cdot x)$一定被打过标记了,这样子可以保证每一个数最多被打过一次标记,复杂度严格$O(n)$。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| bool used[N]; long long prime[N]; long long n,q; void Get_Prime(long long n){ used[1]=1; for(long long i=2;i<=n;i++){ if(!used[i])prime[++prime[0]]=i; for(int j=1;j<=prime[0]&&i*prime[j]<=n;j++){ used[i*prime[j]]=1; if(i%prime[j]==0)break; } } }
|
- 用欧拉筛法线性筛欧拉函数$\varphi$,莫比乌斯函数$\mu$
$\ \ \ \ \ \,$根据欧拉函数$\varphi$的3条性质:
$\ \ \ \ \ \,1$.若$x$为素数,$\varphi(x)=x-1$;
$\ \ \ \ \ \,2$.若$x\%p=0$,$\varphi(x\cdot p)=\varphi(x)\cdot p$;
$\ \ \ \ \ \,3$.若$x\%p\neq 0$,且$p$为素数,$\varphi(x\cdot p)=\varphi(x)\cdot (p-1)$;
$\ \ \ \ \ \,$稍微改动一下线性筛素数就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13
| bool vis[N]; int prim[N],phi[N]; void Get_Phi(int n){ phi[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]){phi[i]=i-1;prim[++prim[0]]=i;} for(int j=1;j<=prim[0]&&i*prim[j]<=n;j++){ vis[i*prim[j]]=1; if(i%prim[j]==0){phi[i*prim[j]]=phi[i]*prim[j];break;} phi[i*prim[j]]=phi[i]*(prim[j]-1); } } }
|
$\ \ \ \ \ \,$根据性质,若$x$为素数,$\mu(x)=-1$;对于任意数$a$,存在$\mu(a\cdot x)=-\mu(a)$。
$\ \ \ \ \ \,$再稍微改动一下线性筛素数就好了。
1 2 3 4 5 6 7 8 9 10 11 12 13
| bool vis[N]; int prim[N],mu[N]; void Get_Mu(int n){ mu[1]=1; for(int i=2;i<=n;i++){ if(!vis[i]){mu[i]=-1;prim[++prim[0]]=i;} for(int j=1;j<=prim[0]&&i*prim[j]<=n;j++){ vis[i*prim[j]]=1; if(i%prim[j]==0)break; mu[i*prim[j]]=-mu[i]; } } }
|
- 对于任意积性函数$f$线性筛
$\ \ \ \ \ \,$对于任意积性函数$f$,我们如何线性筛。
如果$p$是素数:$f(p)=F_1(p)$
如果$p$是素数,$i\%p\neq0$:$f(pi)=f(i)\times F_2(p)$
如果$p$是素数,$i\%p=0$:
我们把 $pi$ 分解成 $p^cx$ ,可以保证 $p^c$ 与 $x$互质,那么有:$f(pi)=f(p^cx)=f(x)*F_3(p,c)$
$\ \ \ \ \ \,$其中,函数$F_1$,$F_2$,$F_3$需要情况制定,模板如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| bool vis[N]; int pri[N],cnt[N],power[N]; int prime[N],f[N]; void Get_Shai(int n){ f[1]=1; for(long long i=1;i<=n;i++)power[i]=1; for(int i=2;i<=n;i++){ if(!vis[i]){ cnt[i]=1;pri[i]=i;power[i]=i; prime[++prime[0]]=i; f[i]=F1(i); } for(int j=1,v,pc;j<=prime[0]&&i*prime[j]<=n;j++){ v=i*prime[j]; vis[v]=1; if(i%prime[j]==0){ cnt[v]=cnt[i]+1;pri[v]=pri[i];power[v]=power[i]*pri[i]; f[v]=f[v/power[v]]*F3(pri[v],cnt[v]); break; } cnt[v]=1;pri[v]=prime[j];power[v]=prime[j]; f[v]=f[i]*F2(prime[j]); } } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cctype> #include<cstdio> #include<vector> #include<string> #include<queue> #include<stack> #include<cmath> #include<map> #include<set> using namespace std; const int inf=0x7fffffff; const double eps=1e-10; const double pi=acos(-1.0);
inline int read(){ int x=0,f=1;char ch;ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=0;ch=getchar();} while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch&15);ch=getchar();} if(f)return x;else return -x; } const int N=1e7+10; int Sig(int a){ int ret=0; for(int i=1;i<=a;i++)if(a%i==0)ret++; return ret; } bool vis[N]; int pri[N],cnt[N],power[N]; int phi[N],mu[N],prime[N],sigma0[N],sigma1[N],inv[N]; void Get_Shai(int n){ phi[1]=mu[1]=sigma0[1]=sigma1[1]=inv[1]=power[1]=1; for(long long i=2;i<=n;i++) inv[i]=(n-n/i)*inv[n%i]%n,power[i]=1; for(int i=2;i<=n;i++){ if(!vis[i]){ cnt[i]=1;pri[i]=i;power[i]=i; prime[++prime[0]]=i; phi[i]=i-1; mu[i]=-1; sigma0[i]=2; sigma1[i]=i+1; } for(int j=1,v,pc;j<=prime[0]&&i*prime[j]<=n;j++){ v=i*prime[j]; vis[v]=1; if(i%prime[j]==0){ cnt[v]=cnt[i]+1;pri[v]=pri[i];power[v]=power[i]*pri[i]; phi[v] =phi[i]*prime[j]; sigma0[v]=sigma0[v/power[v]]*(cnt[v]+1); sigma1[v]=sigma1[v/power[v]]*(power[v]*pri[v]-1)/(pri[v]-1); break; } cnt[v]=1;pri[v]=prime[j];power[v]=prime[j]; phi[v] =phi[i]*(prime[j]-1); mu[v] =-mu[i]; sigma0[v]=sigma0[i]*2; sigma1[v]=sigma1[i]*(prime[j]+1); } } } int main() { int n=read(); Get_Shai(n); for(int i=1;i<=n;i++)printf("%d ",phi[i]);printf("\n"); for(int i=1;i<=n;i++)printf("%d ",mu[i]);printf("\n"); printf("%d ",prime[0]);for(int i=1;i<=prime[0];i++)printf("%d ",prime[i]);printf("\n"); for(int i=1;i<=n;i++)printf("%d ",sigma0[i]);printf("\n"); for(int i=1;i<=n;i++)printf("%d ",sigma1[i]);printf("\n"); for(int i=1;i<=n;i++)printf("%d ",inv[i]);printf("\n"); return 0; }
|