几个常用的筛学习初步模板

普通筛

任务:筛出 N 以内的所有素数
枚举 2 ~ N 之间素数,把素数的倍数置位false,剩下true的就加入到素数表中。复杂度 O(nlogn) 。

bool isPrime[N];
int prime_tot[N];//从 1 开始存储
void prime_table() //普通筛 
{
	int cnt = 0;
	memset(isPrime,true,sizeof(isPrime));
	for(int i = 2; i < N; i++)
	{
		if(isPrime[i])
		{
			prime_tot[++cnt]=i;
			for(int k = 2; k*i < N; k++ )
				isPrime[k*i] = false;
		}
	}
}

线性筛

可以发现普通筛会出现重复筛,比如 2 会筛 6 一次,3 又筛 6 一次,即每个数都由其全部的因子从小到大来筛;而线性筛是利用每个数的最大真因子负责来筛,复杂度为O(n)。

bool isPrime[N];
int prime_tot[N];
void prime_table() //线性筛 
{
	int cnt = 0;
	memset(isPrime,true,sizeof(isPrime));
	for(int i = 2; i < N; i++)
	{
		if(isPrime[i])
			prime_tot[++cnt] = i; 
		for(int j = 1; j <= cnt && prime_tot[j] * i < N; j++) //筛掉i素数倍的合数
		{
			isPrime[prime_tot[j] * i] = false;
			if(i % prime_tot[j] == 0)   //此处重点,倍数不超过 i 的最小素因子
				break;
		}
	}
}

Mobius函数

Alt

在线性筛的基础上顺带处理。

bool isPrime[N];
int prime_tot[N];
int mu[N];
void get_mu() //莫比乌斯函数 
{
	int cnt = 0;
	mu[1] = 1; // n == 1 
	memset(isPrime,true,sizeof(isPrime));
	for(int i = 2; i < N; i++)
	{
		if(isPrime[i])
		{
			prime_tot[++cnt] = i; 
			mu[i] = -1; //质数只含一个因子 
		}
		for(int j = 1; j <= cnt && prime_tot[j] * i < N; j++) 
		{
			isPrime[prime_tot[j] * i] = false;
			if(i % prime_tot[j] == 0)  	// i含平方因子 
				break;
			else 
				mu[prime_tot[j] * i]  = -mu[i];
		}
	}
}

狄利克雷卷积

在这里插入图片描述
(看成函数的运算?)
函数运算满足分配率,交换律,结合律,两积性函数的卷积仍是积性函数。

常见的积性函数
  • 欧拉函数 φ ( x ) \varphi(x) φ(x)
  • 莫比乌斯函数 μ ( x ) \mu(x) μ(x)
  • 单位函数 i d ( n ) = n id(n)=n id(n)=n
  • 不变函数 1 ( n ) = 1 1(n)=1 1(n)=1
  • 狄利克雷卷积单位元 ε = [ n = = 1 ] \varepsilon=[n ==1] ε=[n==1]
    特别地,有 μ ∗ I = ε \mu *I=\varepsilon μI=ε

欧拉函数 φ ( x ) \varphi(x) φ(x)

  • 定义:表示小于等于x的正整数中和x互质的数的个数 。 φ ( 1 ) = 1 \varphi (1)=1 φ(1)=1
  • 有一性质:n的所有因子的 phi 值 加起来等于 n。

在这里插入图片描述

  • 欧拉函数和莫比乌斯函数的关系
    在这里插入图片描述
    可用狄利克雷卷积证明

  • ( φ ∗ I ) ( n ) = i d ( n ) (\varphi*I)(n)=id(n) (φI)(n)=id(n)

  • φ ∗ I ∗ μ = i d ∗ μ \varphi*I*\mu=id*\mu φIμ=idμ

  • φ ( n ) = ∑ d ∣ n n d ∗ μ ( d ) \varphi(n)=\sum_{d|n}\frac{n}{d}*\mu(d) φ(n)=dndnμ(d)

莫比乌斯反演两个公式

  • g ( n ) = ∑ d ∣ n f ( d ) ⟹ g(n)=\sum_{d|n}f(d)\Longrightarrow g(n)=dnf(d) f ( n ) = ∑ d ∣ n μ ( d ) g ( n d ) f(n)=\sum_{d|n}\mu(d)g(\frac{n}{d}) f(n)=dnμ(d)g(dn)
  • g ( n ) = ∑ n ∣ d f ( d ) ⟹ g(n)=\sum_{n|d}f(d)\Longrightarrow g(n)=ndf(d) f ( n ) = ∑ n ∣ d μ ( d n ) g ( d ) f(n)=\sum_{n|d}\mu(\frac{d}{n})g(d) f(n)=ndμ(nd)g(d)

两个公式证明可参照上方用狄利克雷卷积证明的方法。

分块计算

任务:快速计算 ∑ ⌊ n k ⌋ ( 1 ≤ k ≤ n ) \sum\lfloor \frac{n}{k} \rfloor (1\le k\le n) kn(1kn) 复杂度O( 2 n 2\sqrt n 2n )
背景: ⌊ n k ⌋ ( 1 < = k < = n ) \lfloor \frac{n}{k} \rfloor (1<=k<=n) kn(1<=k<=n) 有约 2 n 2\sqrt n 2n 个互不相同的值,比如 n = 21 ,k =1,2,3,4,5,6-7,8-10,11-21,共8个不同的值。(用笔写写,可以发现左右两边是对称的)

int ans = 0;
for(int l = 1,r; l <= n; l = r+1)
{
	r = N / (N / l);
	ans += (r-l+1) * (N/l); //区间个数 * 每个数的贡献值
}

杜教筛

任务: ∑ i = 1 n μ ( i ) , n ≤ 1 0 12 \sum_{i=1}^{n}\mu(i),n\le10^{12} i=1nμ(i),n1012

在这里插入代码片

太弱了,具体的证明过程可参考巨巨们的链接:
peng_ym
https://blog.csdn.net/skywalkert/article/details/50500009

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值