数论---整除与素数---筛法(素数筛,约数个数筛,约数和筛)

本文介绍了数论中的素数定理和整数标准分解,并深入探讨了互质、gcd与lcm、积性函数等概念。接着,重点讲解了筛法,包括埃拉托斯特尼筛(埃筛)和欧拉筛(线性筛),分析了它们的时间复杂度,并展示了如何利用筛法求解约数个数和约数和。文章最后讨论了欧拉筛在减小时间复杂度上的优势。
摘要由CSDN通过智能技术生成

素数定理

整数的标准分解(唯一分解)

#include<cstdio>
int p[105],w[105],k;
void factorize(int n)
{
   
	for(int i=2;i*i<=n;i++)
		if(n%i==0)
		{
   
			p[++k]=i;
			while(n%i==0)
				n/=i,w[k]++;
		}
	if(n!=1)
		p[++k]=n,w[k]=1;
}
int main()
{
   
	int n;
	scanf("%d",&n);
	factorize(n);
	for(int i=1;i<k;i++)
		printf("%d^%d*",p[i],w[i]);
	printf("%d^%d",p[k],w[k]);
}
互质:

互质(Coprime):两个数没有公共的因数(除1以外),则这两个数互质。
将互质的两个数分别唯一分解后,两个积式中不会出现相同质数

gcd与lcm

gcd与lcm

积性函数

例题 codevs6899倒数和分解

在这里插入图片描述

这里有个在数学上比较常用的操作 当a-n的形式出现在分母 不好操作,可以进行还原

关于“一一对应”的理解:n已知,是常数,而要使等式成立,显然不存在一个b的取值时有多个a,所以一定是一一对应的。

※筛法(Sieve Method)※

主要有两类:埃拉托斯特尼筛法(埃筛)和欧拉筛(线性筛),相对来说,欧拉筛的效率更高但理解起来相对困难一点。

埃筛

埃筛是用一个数组标记是否为素数,然后依次筛去这个素数的倍数,代码也比较好理解。

bool sieve()
{
   
	for(int i=2;i<=n;i++)
		if(!vis[i])
		{
   
			prime[++pn]=i;
			for(int j=i*i;j<=n;j+=i)
				vis[j]=1;
		}
}

值得一提的是,第11行的for循环可以从i * i开始而非i * 2(算是一个小优化)吧,因为i * 比i小的数的情况已经在之前的那个数处理过了

比如说i== 7时,可以从7 * 7开始 因为6 * 7,5 * 7的情况都已经分别在i ==6和i ==5的情况中被处理过。


时间复杂度的分析

显然,一些数被重复筛去,所以不是线性的。



筛约数个数,约数和

bool sieve()
{
   
	for(int i=1;i<=n;i++)
		for(int j=i;j<=n;j+=i)
			d[j]++,s[j]+=i;
}

欧拉筛

在埃筛的基础上,让每一个合数都只被他的最小质因子筛去,从而减小时间。

先看一波代码

bool sieve()
{
   
	for(int i=2;i<=n;i++)
	{
   	
		if(!vis[i])
			prime[++pn]=i;
		for(int j=1;j<=pn&&prime[j]*i<=n;j++)
		{
   
			vis[i*prime[j]]=1;
			if(i%prime[j]==0) break;
		}
	}
}
理解

关于vis[i * prime[j]]=1的理解:
这里不是乘上i的多少多少倍,而是把prime数组里面的所有质数当做i * prime[j]的最小质因子来做 也就是消去这个质数的i倍

关于if(i%prime[j]==0) break;的理解:
如果满足i%prime[j]==0,设i=prime[j]*k
那么下一次j++的时候 我们就会筛去s=prime[j+1] *i=prime[j+1] * prime[j] * k ,而这与我们想要让每个数都被他的最小质因子筛去的愿望不符合,因为这个数会在i=prime[j+1]*k 的时候被筛去。

综上,我们可以发现,i*prime[j]的最小质因子为prime[j],当i%prime[j]时,由于prime数组是有序的,i的最小质因子也是prime[j]

欧拉筛求约数个数

d ( n ) d(n) d(n)表示n的约数个数(约数个数函数)
我们先复习一下约数个数的计算方法
n = p 1 w 1 p 2 w 2 p 3 w 3 ⋅ ⋅ ⋅ p m w m n=p_1^{w_1}p_2^{w_2}p_3^{w_3}···p_m^{w_m} n=p1w1p2w2p3w3pmwm
d ( n ) = ( w 1 + 1 ) ( w 2 + 1 ) ( w 3 + 1 ) ⋅ ⋅ ⋅ ( w m + 1 ) d(n)=(w_1+1)(w_2+1)(w_3+1)···(w_m+1) d(n)=(w1+1)(w2+1)(w3+1)(wm+1)
满足 d ( n ) = d ( p 1 w 1 ) d ( p 2 w 2 ) d ( p 3 w 3 ) ⋅ ⋅ ⋅ d ( p m w m ) d(n)=d(p_1^{w_1})d(p_2^{w_2})d(p_3^{w_3})···d(p_m^{w_m}) d(n)=d(p1w1)d(p2w2)d(p3w3)d(pmwm),显然d(n)是积性函数

以下 i i i的意义与上文的欧拉筛中的 i i i意义相同,从2到n进行枚举 我们新定义一个 n u m [ i ] num[i] num[i]表示i的最小质因子的次数
显然 d [ 1 ] = 1 d[1]=1 d[1]=1
分类讨论如下:
①若i是素数 d [ i ] = 2 d[i]=2 d[i]=2
②若 i % p r i m e [ j ] ≠   0 i \%prime[j]\neq\ 0 i%prime[j]̸= 0
i不包含prime[j] i*prime[j]只含有prime[j]的一次方
我们之前已经得到了d[i] 现在加入prime[j]这个新的因子即可


d [ i ∗ p r i m e [ j ] ] = d [ i ] ∗ 2 d[i*prime[j]]=d[i]*2 d[iprime[j]]=d[i]2
n u m [ i ∗ p r i m e [ j ] ] = 1 num[i*prime[j]]=1 num

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值