首页 > 其他分享 >筛法

筛法

时间:2023-10-15 21:12:14浏览次数:37  
标签:prime phi 筛法 NN int ll vis

更新日志:

  • 2023/10/15:发布文章

一、埃氏筛

1. 算法原理

2. 时间复杂度

\(O(n\log{\log {n}})\) 详细证明见oi-wiki

3. 代码实现

bool vis[NN];
int prime[NN],cnt;
typedef long long ll;
void Era(int n){
	for(ll i = 2; i <= n; ++i){
		if(!vis[i]){
			prime[++cnt] = i;
			for(ll j = i * i; j <= n; j += i) vis[j] = 1;//尽量用long long,避免i*i溢出导致的麻烦
		}
	}
}

4. 相关优化

  • 筛至平方根
bool vis[NN];
int prime[NN],cnt;
typedef long long ll;
void Era(int n){
	for(ll i = 2; i * i <= n; ++i){
		if(!vis[i]){
			prime[++cnt] = i;
			for(ll j = i * i; j <= n; j += i) vis[j] = 1;
		}
	}
    for(int i = ceil(sqrt(n)); i <= n; ++i)
        if(!vis[i]) prime[++cnt] = i;
}

可以将复杂度减小至\(~n\ln\ln\sqrt n + o(n)~\)

  • 只筛奇数

除\(~2~\)以外的偶数都不是质数

bool vis[NN];
int prime[NN],cnt;
typedef long long ll;
void Era(int n){
   	prime[++cnt] = 2;//change1
	for(ll i = 3; i <= n; i += 2){//change2
		if(!vis[i]){
			prime[++cnt] = i;
			for(ll j = i * i; j <= n; j += i * 2) vis[j] = 1;//change3
		}
	}
}

二、 线性筛

1. 算法原理

我们考虑对埃氏筛进行优化

我们研究会发现,在埃氏筛中,一些合数会被筛多次,例如:

\(~12 = 2 \times 6 = 3 \times 4~\),即\(~12~\)在\(\begin{cases}i = 2\\j = 6\end{cases}\)和$$\begin{cases}i = 3\j = 4\end{cases}$$会被重复筛选

那如何规避呢,我们就只让一个数最小的质因子筛这个数,让每个合数只被标记一次

2. 代码实现

bool vis[NN];
int prime[NN],cnt;
void init(){
	for(int i = 2; i <= n; ++i){
		if(!vis[i]) pri[++cnt] = i;
		for(int j = 1; j <= cnt; ++j){
		    if (1ll * i * pri[j] > n) break;
		    vis[i * pri[j]] = 1;
		    if(i % pri[j] == 0) break;
    	}
	}
}

3. 线性筛求欧拉函数

设\(~p_1~\)为\(~n~\)的最小质因子,设\(~n'=\frac n {p_1}~\)

那么由欧拉函数定义可得:

\[\begin{cases}\varphi(n) = n\times\prod\limits_{i=1}^{s}\frac {p_i-1}{p_i} = p_1\times\varphi(n') & n'~mod~p_1 = 0\\\varphi(n) = (p_1-1)\times\varphi(n')&n'~mod~p_1\not=0\end{cases} \]

再根据线性筛进行修改即可

bool vis[NN];
int prime[NN],cnt,phi[NN];
void Euler(){
    phi[1] = 1;
	for(int i = 2; i <= n; ++i){
		if(!vis[i]){pri[++cnt] = i;phi[i] = i - 1;}
		for(int j = 1; j <= cnt; ++j){
		    if (1ll * i * pri[j] > n) break;
            vis[i * pri[j]] = 1;
		    if(i % pri[j] == 0){
                phi[i*prime[j]] = prime[j] * phi[i];
                break;
            }
            else phi[i*prime[j]] = phi[i] * phi[prime[j]];
    	}
	}
}

标签:prime,phi,筛法,NN,int,ll,vis
From: https://www.cnblogs.com/rickylin/p/17766178.html

相关文章

  • 数论筛法小记
    BaseSievebaseDirichletConvolutionSqrtDecomposition会挖坑,好让复习的时候长脑子。以下所有\(p\)都是质数,即\(p\in\mathbb{P}\),同时默认均为正整数。Base唯一分解定理(算术基本定理):\[\begin{align} \foralln>1,n=\prod\limits_{i=1}^kp_i^{t_i}\end{align}\]......
  • 素数的判定:筛法
    素数很有用,特别是在密码学领域中,比如RSA中很重要的一步就是寻找两个比较大的素数,通常的做法是先随机生成一个大整数,然后使用一些素性判定的方法,比如费马素性测试。在算法竞赛的数论题目中,素数也很常见,通常的做法是先找出一定范围内的所有素数,用到时再查表,筛法就可以做到。1.埃氏......
  • 筛法求约数个数
    推荐视频:516筛法求约数个数点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineLLlonglongconstintN=1e8+10;intp[N],cnt;intd[N];//d[i]记录i的约数的个数inta[N];//a[i]记录i的最小质因子的次数boolvis[N];voidget_d(intn){//筛法求......
  • 数学筛法
    有的时候怕忘记,写篇小博客记录一下。线性筛素数inlinevoidinit(intn){for(inti=2;i<=n;i++){if(!vis[i])prime[++cnt]=i;for(intj=1;j<=cnt&&i*prime[j];j++){vis[i*prime[j]]=1;if(!(i%prime[j]))br......
  • 素数—埃式筛法
    埃式筛法思路 利用当前已经确定的素数筛选掉非素数的自然数,然后向后选择没有被筛选的自然数,即素数,重复上述操作。实现打印[1,100]区间的素数#include<iostream>#include<vector>usingnamespacestd;intmain(){vector<int>prime;vector<bool>isPrime(11......
  • js找出一定范围内的全部素数(埃拉托斯特尼筛法Sieve of Eratosthenes)
    最近在看js的基础,看到函数这一章的时候,看到了这种写法。 原文链接:https://zh.javascript.info/function-basics突然懵了个B,js还能这么写。然后问了下chat,才想起来这是js的标签用法。在JavaScript中,标签(label)是一种标识符,用于标记代码中的特定位置,通常是在循环语句中使用。标......
  • python用筛法输出指定范围素数个数
    1importtime2stime=time.time()3defq(n):4is_prime={x:Trueforxinrange(n+1)}#生成一个n个元素的字典key设置为0-n+1值设置为True5delis_prime[0]#删除06forcin(2,3,5,7):7forzinrange(2,int(n/2)):8......
  • 【学习笔记】数论之筛法
    前言:可以会乱记一些技巧吧。交换求和顺序如果不确定可以将条件写成[A]的形式,交换完求和顺序再把这个条件放里面。例如:\[\sum_{i=1}^n\sum_{d}[d|i]=\sum_{d=1}^n\sum_{i}[d|i]=\sum_{d=1}^n\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}1\]狄利克雷前缀和与狄利......
  • 算法学习笔记(28): 筛法
    筛法线性筛杜教筛放在偏序关系\((\Z,|)\)中卷积……如何快速的求\(S(n)=\sum_{i=1}^nf(i)\)。如果能够找到一个函数\(g\):\[\begin{aligned}\sum_{i=1}^n(f*g)(i)&=\sum_{i=1}^n\sum_{d|i}f(\fracid)g(d)\\&=\sum_{d=1}^{n}g(d)\sum_{i......
  • 筛法对比
    杜教筛博客链接时间复杂度\(O(n^\frac{2}{3})\)要求:构造一个\(g\)满足\((f*g)\)易于计算前缀和,\(g\)易于计算前缀和。注意并没有要求\(g\)和\(f*g\)是一个积性函数。杜教筛可以多次运用,例如筛\(f=\phi*\phi*\mu\),可以筛\(f*I=\phi*\phi\),这样只需要解决\(g......