《算法竞赛进阶指南》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

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

poj 3974 and hdu 3068 最长回文串的O(n)解法(Manacher算法)

求一段字符串中的最长回文串。 因为数据量比较大,用原来的O(n^2)会爆。 小白上的O(n^2)解法代码:TLE啦~ #include<stdio.h>#include<string.h>const int Maxn = 1000000;char s[Maxn];int main(){char e[] = {"END"};while(scanf("%s", s) != EO

秋招最新大模型算法面试,熬夜都要肝完它

💥大家在面试大模型LLM这个板块的时候,不知道面试完会不会复盘、总结,做笔记的习惯,这份大模型算法岗面试八股笔记也帮助不少人拿到过offer ✨对于面试大模型算法工程师会有一定的帮助,都附有完整答案,熬夜也要看完,祝大家一臂之力 这份《大模型算法工程师面试题》已经上传CSDN,还有完整版的大模型 AI 学习资料,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费