欧拉筛与欧拉函数表的实现

欧拉筛

欧拉筛是较之于埃氏筛的一种更高效的素数筛法。

线性筛,复杂度为O(n)。与埃氏筛相比,不会对已经被标记过的合数再进行重复标记,故效率更高。欧拉筛将合数分解为 (最小质因数 * 一个合数) 的形式,通过最小质因数来判断当前合数是否已经被标记过。

我的代码

int prm[N],tot=0;				//prm为质数组,tot记质数个数
bool boo[N];					//标记是否为质数
void prime(){
	memset(boo,0,sizeof(boo));	//标记质数为0,合数为1;
	for(int i=2;i<=N-7;i++){
		if(!boo[i]){			//如果还没被标为合数
			prm[++tot]=i;		//i就是第tot+1个质数
		}	
		for(int j=1;j<=tot&&i*prm[j]<=N-7;j++){
			boo[i*prm[j]]=1;	//用i做倍数,第j个质数的i倍都是合数
			if(i%prm[j]==0){	//核心步骤
				break;
			}
		}
	}
}

对于核心步骤,引用一下别人的解释

对于 i%prime[j] == 0 就break的解释 :当 i是prime[j]的倍数时,i = kprime[j],如果继续运算 j+1,i * prime[j+1] = prime[j] * k prime[j+1],这里prime[j]是最小的素因子,当i = k * prime[j+1]时会重复,所以才跳出循环。
举个例子 :i = 8 ,j = 1,prime[j] = 2,如果不跳出循环,prime[j+1] = 3,8 * 3 = 2 * 4 * 3 = 2 * 12,在i = 12时会计算。因为欧拉筛法的原理便是通过最小素因子来消除。
————————————————
版权声明:本文为CSDN博主「彤云望月」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39763472/article/details/82428602

若将一个合数n=i * prm[j],称为n被prm[j]标记,若i%prm[j]==0,那么合数m=i%prm[j+1]不需被prm[j+1]标记,随着i增长,它会被它的最小质因子prm[j]标记。

欧拉函数

在上述代码的基础上增加数组phi[N],可快速求出欧拉函数表。并没有用欧拉函数的公式
在这里插入图片描述
p1…pn是x的所有质因数

在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目(因此φ(1)=1)。

特性 :
1.若a为质数,phi[a]=a-1;
2.若a为质数,b mod a=0,phi[a*b]=phi[b]*a
3.若a,b互质,phi[a*b]=phi[a]*phi[b](当a为质数时,if b mod a!=0 ,phi[a*b]=phi[a]*phi[b])

void euler(){
	memset(boo,0,sizeof(boo));
	phi[1]=1;
	for(int i=2;i<=N-7;i++){
		if(!boo[i]){
			prm[++tot]=i;
			phi[i]=i-1;			//新增行,特性1
		}	
		for(int j=1;j<=tot&&i*prm[j]<=N-7;j++){
			boo[i*prm[j]]=1;
			if(i%prm[j]==0){
				phi[i*prm[j]]=phi[i]*prm[j];		//新增行,特性2
				break;
			}
			else phi[i*prm[j]]=phi[i]*phi[prm[j]];	//新增行,特性3
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值