积性函数线性筛
OI中有时需要我们线性筛某些函数,我们筛的主要是积性函数
1st:线性筛素数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include<iostream> #include<cstdio> using namespace std; const int MAXN=1e4+5; int N,prime[MAXN],vis[MAXN],tot; void get_prime( int N){ vis[1]=1; for ( int i=2;i<=N;i++){ if (!vis[i]) prime[++tot]=i; for ( int j=1;j<=tot&&i*prime[j]<=N;j++){ vis[i*prime[j]]=1; if (!(i%prime[j])) break ; } } } int main(){ get_prime(1e3); for ( int i=1;i<=tot;i++) printf ( "%d " ,prime[i]); return 0; } |
2nd:欧拉函数线性筛:
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 | #include<iostream> #include<cstdio> using namespace std; const int MAXN=1e4+5; int n,prime[MAXN],vis[MAXN],phi[MAXN],tot; void get_phi( int n){ vis[1]=phi[1]=1; for ( int i=2;i<=n;i++){ if (!vis[i]) prime[++tot]=i,phi[i]=i-1; for ( int j=1;j<=tot&&i*prime[j]<=n;j++){ vis[i*prime[j]]=1; if (!(i%prime[j])){ phi[i*prime[j]]=phi[i]*prime[j]; break ; } phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } } int main(){ get_phi(1e3); for ( int i=1;i<=tot;i++) printf ( "%d " ,phi[i]); return 0; } |
欧拉函数其他求法:
求单个数的欧拉函数:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n; 7 int phi(int N){ 8 int m=N; 9 for(int i=2;i*i<=N;++i){ 10 if(N%i==0){ 11 m=m/i*(i-1); 12 while(N%i==0) N/=i; 13 } 14 } 15 if(N>1) m=m/N*(N-1); 16 return m; 17 } 18 int main(){ 19 scanf("%d",&n); 20 printf("%d\n",phi(n)); 21 return 0; 22 }
复杂度略大于线性的求法:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,phi[1000006]; 7 void get_phi(int N){ 8 for(int i=1;i<=N;++i) phi[i]=i; 9 for(int i=2;i<=N;++i){ 10 if(phi[i]==i){ 11 for(int j=i;j<=N;j+=i){ 12 phi[j]=phi[j]/i*(i-1); 13 } 14 } 15 } 16 } 17 int main(){ 18 scanf("%d",&n); 19 get_phi(n); 20 for(int i=1;i<=n;++i){ 21 printf("%d\n",phi[i]); 22 } 23 return 0; 24 }
欧拉函数一个性质:∑d|nϕ(d)=n
3rd:莫比乌斯函数线性筛(虽然我不知道莫比乌斯函数是什么以及怎么用)
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 | #include<iostream> #include<cstdio> using namespace std; const int MAXN=1e4+5; int n,prime[MAXN],vis[MAXN],mu[MAXN],tot; void get_mu( int n){ vis[1]=mu[1]=1; for ( int i=2;i<=n;i++){ if (!vis[i]) prime[++tot]=i,mu[i]=-1; for ( int j=1;j<=tot&&i*prime[j]<=n;j++){ vis[i*prime[j]]=1; if (!(i%prime[j])){ mu[i*prime[j]]=0; break ; } mu[i*prime[j]]=mu[i]*mu[prime[j]]; //根据莫比乌斯函数的定义,这里也可以写为 //mu[i*prime[j]]=-mu[i]; } } } int main(){ get_mu(1e3); for ( int i=1;i<=tot;i++) printf ( "%d " ,mu[i]); puts ( "" ); return 0; } |
4th:线性筛约数个数:
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 | #include<iostream> #include<cstdio> using namespace std; const int MAXN=1e4+5; int n,prime[MAXN],vis[MAXN],d[MAXN],tot,a[MAXN]; void get_d( int n){ vis[1]=d[1]=a[1]=1; for ( int i=2;i<=n;i++){ if (!vis[i]) prime[++tot]=i,d[i]=2,a[i]=1; for ( int j=1;j<=tot&&i*prime[j]<=n;j++){ vis[i*prime[j]]=1; if (!(i%prime[j])){ d[i*prime[j]]=d[i]/(a[i]+1)*(a[i]+2); a[i*prime[j]]=a[i]+1; break ; } d[i*prime[j]]=d[i]*d[prime[j]]; a[i*prime[j]]=1; } } } int main(){ get_d(1e3); for ( int i=1;i<=tot;i++) printf ( "%d " ,d[i]); puts ( "" ); return 0; } |
5th:线性筛约数和:
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 | #include<iostream> #include<cstdio> using namespace std; const int MAXN=1e4+10; int N,prime[MAXN],vis[MAXN],SD[MAXN],sum[MAXN],low[MAXN],tot; void GetSumD( int N){ vis[1]=SD[1]=low[1]=sum[1]=1; for ( int i=2;i<=N;i++){ if (!vis[i]) prime[++tot]=i,sum[i]=SD[i]=i+1,low[i]=i; for ( int j=1;j<=tot&&i*prime[j]<=N;j++){ vis[i * prime[j]]=1; if (!(i%prime[j])){ low[i*prime[j]]=low[i]*prime[j]; sum[i*prime[j]]=sum[i]+low[i*prime[j]]; SD[i*prime[j]]=SD[i]/sum[i]*sum[i*prime[j]]; break ; } low[i*prime[j]]=prime[j]; sum[i*prime[j]]=prime[j]+1; //这里low和sum不是积性函数 SD[i*prime[j]]=SD[i]*SD[prime[j]]; } } } int main() { GetSumD(1e3); for ( int i=1;i<=tot;i++) printf ( "%d " ,SD[i]); puts ( "" ) return 0; } |
6th:其他积性函数?卷积?不会了。。。
伪代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | vis[1] = low[1] = 1; H[1] = 初始化 for ( int i = 2; i <= N; i++) { if (!vis[i]) prime[++tot] = i, mu[i] = -1, H[i] = 质数的情况, low[i] = i; for ( int j = 1; j <= tot && i * prime[j] <= N; j++) { vis[i * prime[j]] = 1; if (!(i % prime[j])) { low[i * prime[j]] = (low[i] * prime[j]); if (low[i] == i) H[i * prime[j]] = 特殊判断; else H[i * prime[j]] = H[i / low[i]] * H[prime[j] * low[i]]; break ; } H[i * prime[j]] = H[i] * H[prime[j]]; low[i * prime[j]] = prime[j]; } } |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· Winform-耗时操作导致界面渲染滞后
· Phi小模型开发教程:C#使用本地模型Phi视觉模型分析图像,实现图片分类、搜索等功能
· 语音处理 开源项目 EchoSharp
· drools 规则引擎和 solon-flow 哪个好?solon-flow 简明教程