基础数论 质数与约数
前置芝士:#
等比数列求和:
质数与约数:#
整除与约数#
设
质数与合数的定义:#
对于
质数判定:#
试除法:
单次时间复杂度
代码
bool is_prime(int n) {
if(n < 2)
return false;
for(int i=2; i<= sqrt(n); ++i) {
if(n % i == 0)
return false;
}
return true;
}
质数筛法一:
从
时间复杂度
代码
void found_prime() {
memset(vis, 0, sizeof(vis));
vis[0] = 1; vis[1] = 1; // 特殊处理 0 和 1
for(int i=2; i<=n; ++i) {
for(int j=i*2; j<=n; j+=i)
vis[j] = 1; // 标记合数
}
}
埃氏筛:
只需要枚举质数的倍数就可以标记到所有合数了。实际上对于每个质数
从
时间复杂度
代码
void found_prime() {
memset(vis, 0, sizeof(vis));
vis[0] = 1; vis[1] = 1; // 特殊处理 0 和 1
for(int i=2; i<=n; ++i) {
if(!vis[i]) { // i 为质数
for(int j=i*i; j<=n; j+=i)
vis[j] = 1; // 标记合数
}
}
}
线性筛:
用每一个合数的最小质因子来标记这个合数。时间复杂度
代码
int pr[N],cnt;
bool vis[N];
void init(){
int n=1e5+50;
for(int i=2;i<=n;i++){
if(!vis[i]){pr[++cnt]=i;}
for(int j=1;j<=cnt&&i*pr[j]<=n;j++){
vis[i*pr[j]]=1;
if(i%pr[j]==0)break;
}
}
}
区间筛:(埃氏筛)
代码
const int maxn = 1e6+10;
typedef long long LL;
bool is_prime[maxn]; //标记a~b范围内的质数
bool is_prime_small[maxn]; //标记 1~sqrt(n)范围内的所有质数
LL a, b;
//对区间[a, b]内的整数执行筛法,is_prime[i-a]=true表示i是素数
void found_prime()
{
for(LL i=0; i*i<=b; ++i)
is_prime_small[i] = true;
is_prime_small[1] = false;
for(LL i=0; i<=b-a; ++i)
is_prime[i] = true;
for(LL i=2; i*i<=b; ++i) {
if(is_prime_small[i]) { // i是质数
for(LL j=i*i; j*j<=b; j+=i) // 标记 sqrt(b) 以内的i的倍数
is_prime_small[j] = false;
for(LL j = max(2LL, (a+i-1)/i) * i; j<=b; j+=i) //标记[a, b]中i的倍数
is_prime[j-a] = false;
}
}
}
算术基本定理:#
任何一个大于 1 的正整数都能唯一分解为若干个质数的乘积。
设
其中
根据算术基本的定理,对于任意一个大于
推论一:
推论二:
阶乘分解:#
对于一个数
考虑对于一个质数
求 中包含多少个
答案是
对于每一个质数都用如上方式
共有个数,每次处理 的复杂度,总复杂度 。
求解正约数集合:#
试除法 求
时间复杂度
代码
int divisor[10010], cnt = 0;
for(int i=1; i<=sqrt(n); ++i) {
if(n % i == 0) {
divisor[++cnt] = i;
if(i != n/i) divisor[++cnt] = n/i;
}
}
推论:一个整数
倍数法 求
先枚举
代码
vecotr<int> divisor[500010];
for(int i=1; i<=n; ++i) { // 先枚举约数 i
for(int j=1; j<=n/i; ++j) //枚举 i 在 1~n 范围内的倍数 i × j
divisor[i*j].push_back(i); // i 是 i × j 的约数
}
推论:
约数研究:#
设
可以枚举每一个
, 中含有 个约数 。所以答案为
:#
性质:
- 对于
若 则称 互质。 - 由于任何正整数都是
和 的公约数,故 不存在。 - 对于
,有 。 ,有 。
更相减损术:#
,有 ,则 ,所以 也是 的公约数,所以 。
辗转相除法:#
- 若
,则 - 若
,设 ,其中 。 。有 ,则 ,因此 ,也是 的公约数,故
代码:
代码
int gcd(int a, int b) {
while(b > 0 ) {
int x = a % b;
a = b;
b = x;
}
return a;
}
递归:
代码
int gcd(int a, int b) {
return b ? gcd(b, a%b) : a;
}
最大复杂度
:#
实际代码中:
gcd与lcm:#
给出某两个整数
设,从 来枚举 ,当 时停止枚举。
答案即为
CF1152C:#
给定两个正整数
设
显然
由辗转相除法可知
所以
所以可以枚举的因子 ,若 则 ,否则
by ysx
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探