《算法竞赛进阶指南》0x31质数

2024-08-29 09:52

本文主要是介绍《算法竞赛进阶指南》0x31质数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

定义

若一个正整数无法被除了1和它本身之外的任何自然数整除,则称这个数为质数(素数),反之为合数。
对于一个足够大的整数N,不超过N的质数大约有 N/lnN个,分布比较松散。

质数的判定

试除法
若一个正整数N为合数,则存在一个能整除N的数T,其中 2 ≤ T ≤ N 2\leq T \leq \sqrt{N} 2TN

因此,我们只需要扫描 [ 2 , N ] [2,\sqrt{N}] [2,N ]之间的所有整数,一次检查能否整除N,若不能则N是质数,否则N是合数。

bool is_prime(int n)
{if (n < 2) return false;for (int i = 2; i <= sqrt(n); i ++ )if (n % 2 == 0) return false;return true;
}

质数的筛选

给定一个整数N,求出[1,n]之间所有的质数,称为质数的筛选问题。

Erathosthenes筛法
Erathosthenes筛法基于这样的思想,任意整数x的倍数都不是质数,我们可以从2开始,从小到大扫描每一个数,把他们的倍数标记为合数。当扫描到一个数时,如果没有被标记,那么就是质数。

void primes(int n)
{memset(st, 0, sizeof st);for (int i = 2; i <= n; i ++ ){if (st[i]) continue;prime[cnt ++ ] = i;for (int j = i; j <= n / i; j ++ ) st[i * j] = 1;}
}

时间复杂度为 O ( n l o g l o g n ) = n ∗ ( 1 / 2 + 1 / 3 + 1 / 5 + 1 / 7 + . . . + 1 / n ) = n l o g l o g n 时间复杂度为O(nloglogn)=n*(1/2+1/3+1/5+1/7+...+1/n)=nloglogn 时间复杂度为O(nloglogn)=n(1/2+1/3+1/5+1/7+...+1/n)=nloglogn

线性筛法
线性筛法通过“从大到小累积质因子”的方式标记每个合数。
1.依次考虑[2,n]之间的每一个数i。
2.若st[i]=0,说明i是质数,保存下来。
3.扫描每个质数p,令v[i*p]=p.也就是在i的基础上累计一个质因子p。因为p<=i的最小质因子,所以p就是合数i*p的最小质因子。

void primes(int n)
{memset(st, 0, sizeof st);cnt = 0;for (int i = 2; i <= n; i ++ ){if (!st[i]) prime[cnt ++ ] = i;for (int j = 0; i * prime[j] <= n; j ++ ){st[i * prime[j]] = true;if (i % prime[j] == 0) break;}}
}

每个合数i*p只会被最小质因子p筛一次,时间复杂度为O(n)。

质因数分解

任何一个大于1的正整数都能唯一分解成有限个质数的乘积,可写作:
N = p 1 c 1 p 2 c 2 . . . p m c m N=p_1^{c1}p_2^{c2}...p_m^{cm} N=p1c1p2c2...pmcm
其中ci为正整数,pi为质数,且 p 1 < p 2 < . . . < p n p_1 < p_2 < ... <pn p1<p2<...<pn

试除法

void divide(int n)
{m = 0;for (int i = 2; i <= sqrt(n); i ++ ){if (n % 2 == 0){p[ ++ m] = i, c[m] = 0;while (n % i == 0) n /= i, c[m] ++ ;}}if (n > 1) p[ ++ m] = 1, c[m] = 1;for (int i = 1; i <= m; i ++ )cout << p[i] << '^' << c[i] << endl;
}

时间复杂度为 O ( n ) O(\sqrt{n}) O(n )

例题

acwing196.质数距离

如果直接使用线性筛求出[2,r]之间的所有质数的话时间复杂度为T*10^9,显然会超时,我们考虑使用线性筛求出 [ 2 , r ] [2,\sqrt{r}] [2,r ]之间所有的素数,对于每个素数,把[l,r]中能被该质数整除的数标记。

时间复杂度分为两部分,线性筛的时间复杂度加上求区间合数的时间复杂度。
前者时间复杂度为 O ( r ) O(\sqrt{r}) O(r )
后者时间复杂度为 ( r − l ) / 2 + ( r − l ) / 3 + ( r − l ) / 5 + . . . + ( r − l ) / r = O ( ( r − l ) ∗ ( l o g l o g n ) ) (r-l)/2+(r-l)/3+(r-l)/5+...+(r-l)/\sqrt{r}=O((r-l)*(loglog\sqrt{n})) (rl)/2+(rl)/3+(rl)/5+...+(rl)/r =O((rl)(loglogn ))
总和为 O ( T ∗ ( r + ( r − l ) ∗ ( l o g l o g n ) ) ) O(T*(\sqrt{r}+(r-l)*(loglog\sqrt{n}))) O(T(r +(rl)(loglogn )))

#include <iostream>
#include <cstring>
using namespace std;
#define N 1000010
typedef long long ll;
bool st[N];
int prime[N];
int cnt = 0;
void init(int n)
{memset(st, 0, sizeof st);cnt = 0;for (int i = 2; i <= n; i ++ ){if (!st[i]) prime[cnt ++ ] = i;for (int j = 0; i * prime[j] <= n; j ++ ){st[i * prime[j]] = true;if (i % prime[j] == 0) break;}}
}
int main()
{int l, r;while (cin >> l >> r){init(500000);memset(st, 0, sizeof st);for (int i = 0; i < cnt; i ++ ){ll p = prime[i];for (ll j = max(2 * p, (l - 1 + p) / p * p); j <= r; j += p)st[j - l] = true;}cnt = 0;for (int i = 0; i <= r - l; i ++ ){if (!st[i] && i + l >= 2) prime[cnt ++ ]  = i + l;}if (cnt < 2) puts("There are no adjacent primes.");else{int minp = 0, maxp = 0;for(int i = 0; i < cnt - 1; i ++ ){int d = prime[i + 1] - prime[i];if (d < prime[minp + 1] - prime[minp]) minp = i;if (d > prime[maxp + 1] - prime[maxp]) maxp = i;}printf("%d,%d are closest, %d,%d are most distant.\n",prime[minp], prime[minp + 1], prime[maxp], prime[maxp + 1]);}}return 0;
}

acwing197.阶乘分解
首先排除先求出阶乘再用试除法分解质因数的方法。
再排除对于1-n每一个整数分解质因数,最后进行整合的方法,因为这样的时间复杂度为 O ( n n ) O(n\sqrt{n}) O(nn ),依然会超时。
考虑枚举质数,因为N!的阶乘的质因数肯定不会大于N,所以找丛2到N的所有质数p。
对于每一个p^k,求其会贡献多少个质数p的数量,即
⌊ N / p ⌋ + ⌊ N / p 2 ⌋ + ⌊ N / p 3 ⌋ + . . . + ⌊ N / p k ⌋ \lfloor N/p \rfloor+\lfloor N/p^2 \rfloor+\lfloor N/p^3 \rfloor+...+\lfloor N/p^k \rfloor N/p+N/p2+N/p3+...+N/pk
一共有 l o g p n log_p^n logpn项,可以以O(1)的时间求出每一项的值。又因为前n个数中质数数量为n/logn,所以 l o g 2 n + l o g 3 n + l o g 5 n . . . < l o g 2 n ∗ n / l o g 2 n = n log_2^n+log_3^n+log_5^n...<log_2^n *n/log_2^n = n log2n+log3n+log5n...<log2nn/log2n=n
所以总体时间复杂度为 O ( n ) O(n) O(n)

#include <iostream>
using namespace std;
#define N 1000010
bool st[N];
int prime[N];
int n, cnt = 0;
typedef long long ll;
void init(int n)
{for (int i = 2; i <= n; i ++ ){if(!st[i]) prime[cnt ++ ] = i;for (int j = 0; prime[j] * i <= n; j ++ ){st[i * prime[j]] =true;if (i % prime[j] == 0)break;}}
}
int main()
{cin >> n;init(n);for (int i = 0; i < cnt; i ++ ){int p = prime[i];int s = 0;for (ll j = p; j <= n; j *= p)s += n / j;printf("%d %d\n", p, s);}return 0;
}

这篇关于《算法竞赛进阶指南》0x31质数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1117527

相关文章

golang字符串匹配算法解读

《golang字符串匹配算法解读》文章介绍了字符串匹配算法的原理,特别是Knuth-Morris-Pratt(KMP)算法,该算法通过构建模式串的前缀表来减少匹配时的不必要的字符比较,从而提高效率,在... 目录简介KMP实现代码总结简介字符串匹配算法主要用于在一个较长的文本串中查找一个较短的字符串(称为

Nginx实现动态封禁IP的步骤指南

《Nginx实现动态封禁IP的步骤指南》在日常的生产环境中,网站可能会遭遇恶意请求、DDoS攻击或其他有害的访问行为,为了应对这些情况,动态封禁IP是一项十分重要的安全策略,本篇博客将介绍如何通过NG... 目录1、简述2、实现方式3、使用 fail2ban 动态封禁3.1 安装 fail2ban3.2 配

通俗易懂的Java常见限流算法具体实现

《通俗易懂的Java常见限流算法具体实现》:本文主要介绍Java常见限流算法具体实现的相关资料,包括漏桶算法、令牌桶算法、Nginx限流和Redis+Lua限流的实现原理和具体步骤,并比较了它们的... 目录一、漏桶算法1.漏桶算法的思想和原理2.具体实现二、令牌桶算法1.令牌桶算法流程:2.具体实现2.1

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

JavaScript中的reduce方法执行过程、使用场景及进阶用法

《JavaScript中的reduce方法执行过程、使用场景及进阶用法》:本文主要介绍JavaScript中的reduce方法执行过程、使用场景及进阶用法的相关资料,reduce是JavaScri... 目录1. 什么是reduce2. reduce语法2.1 语法2.2 参数说明3. reduce执行过程

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

SQL Server数据库迁移到MySQL的完整指南

《SQLServer数据库迁移到MySQL的完整指南》在企业应用开发中,数据库迁移是一个常见的需求,随着业务的发展,企业可能会从SQLServer转向MySQL,原因可能是成本、性能、跨平台兼容性等... 目录一、迁移前的准备工作1.1 确定迁移范围1.2 评估兼容性1.3 备份数据二、迁移工具的选择2.1

在 Windows 上安装 DeepSeek 的完整指南(最新推荐)

《在Windows上安装DeepSeek的完整指南(最新推荐)》在Windows上安装DeepSeek的完整指南,包括下载和安装Ollama、下载DeepSeekRXNUMX模型、运行Deep... 目录在www.chinasem.cn Windows 上安装 DeepSeek 的完整指南步骤 1:下载并安装

nginx-rtmp-module构建流媒体直播服务器实战指南

《nginx-rtmp-module构建流媒体直播服务器实战指南》本文主要介绍了nginx-rtmp-module构建流媒体直播服务器实战指南,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. RTMP协议介绍与应用RTMP协议的原理RTMP协议的应用RTMP与现代流媒体技术的关系2