各种筛法与莫比乌斯反演

先挖个坑,以后来填。

大佬的讲解连接【IN

目前有的筛法有:

  • 诶氏筛
  • 扩展诶氏筛
  • 欧拉筛(筛一类积性函数)
  • 杜教筛
  • 洲阁筛
  • Min_25筛【模板IN

上几份模板代码

  • 线性筛素数
P3383
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int M=1e7+10;
int p[M];
bool vis[M];
int n,cnt,m;
void sift(int a){
	vis[0]=vis[1]=1;
	for(int i=2;i<=a;i++){
		if(!vis[i]) p[++cnt]=i;
		for(int j=1;j<=cnt&&p[j]*i<=a;j++){
			vis[p[j]*i]=1;
			if(i%p[j]==0) break;
		}
	}
}
int a;
int main(){
	scanf("%d%d",&n,&m);
	sift(n);
	for(int i=1;i<=m;i++){
		scanf("%d",&a);
		if(vis[a]) printf("No\n");
		else printf("Yes\n");
	}
	return 0;
}

  • 线性筛欧拉函数和莫比乌斯函数
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=1e5+10;
int mob[M],prime[M],cnt;
bool notp[M];
void Mobius(int n){
	mob[1]=1;
	for(int i=2;i<=n;i++){
		if(!notp[i]) prime[++cnt]=i,mob[i]=-1;
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			notp[i*prime[j]]=1;
			if(i%prime[j]){
				mob[i*prime[j]]=-mob[i];
			}else{
				mob[i*prime[j]]=0;
				break;
			}
		}
	}
}
int phi[M];
void euler(int n){
	phi[1]=1;
	for(int i=2;i<=n;i++){
		if(notp[i]) prime[++cnt]=i,phi[i]=i-1;
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			notp[i*prime[j]]=1;
			if(i%prime[j]){
				phi[i*prime[j]]=phi[i]*(prime[j]-1);
			}else{
				phi[i*prime[j]]=phi[i]*prime[j];
				break;
			}
		}
	}
}
可以合在一起写
  • 线性筛约数个数与约数个数和
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int M=1e5+10;
int prime[M],cnt,gdiv[M],sdiv[M];
bool nop[M];
int num[M],sp[M];

void init(int n){
	gdiv[1]=sdiv[1]=1;
	for(int i=2;i<=n;i++){
		if(!nop[i]) prime[++cnt]=i,gdiv[i]=2,num[i]=1,sdiv[i]=sp[i]=1+i;
		for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
			nop[i*prime[j]]=1;
			if(i%prime[j]){
				gdiv[i*prime[j]]=gdiv[i]*gdiv[prime[j]];num[i*prime[j]]=1;
				sdiv[i*prime[j]]=sdiv[i]*sdiv[prime[j]];
				sp[i*prime[j]]=1+prime[j];
			}else{
				gdiv[i*prime[j]]=gdiv[i]/(num[i]+1)*(num[i]+2);num[i*prime[j]]=num[i]+1;
				sdiv[i*prime[j]]=sdiv[i]/sp[i]*(sp[i]*prime[j]+1);
				sp[i*prime[j]]=sp[i]*prime[j]+1;
				break;
			}
		}
	}
}


int main(){
	init(20);
	for(int i=1;i<=20;i++){
		printf("%d : %d %d\n",i,gdiv[i],sdiv[i]);
	}
}
https://blog.csdn.net/ControlBear/article/details/77527115
posted @ 2018-08-09 14:56  VictoryCzt  阅读(251)  评论(0编辑  收藏  举报