数论
数论基础#
整除#
只在整数域上讨论。
一般形式为
其性质在此不过多叙述。
约数#
与整除相关。若
在具体问题中,如果没有特别说明,约数总是指正约数 。
最大公因数和最小公倍数#
即
最大公约数有如下性质:
- 若
,则 。进而- 对不全为
的整数 和非零整数 , - 对不全为
的整数 ,若 ,则
最小公倍数有如下性质:
- 若
,则 - 若
,则 。进而- 若
,则
最大公约数和最小公倍数可以组合出很多奇妙的等式,如:
互素#
若
多个整数互素,不一定两两互素。例如
素数#
若一整数
算术基本引理#
通过素数的性质我们可得:
若
算术基本定理(唯一分解定理)#
设一正整数
这样的形式称作
同余#
即除以某数的余数相同。
记为同余式:
性质:
- 同余是等价关系,即同余具有
- 自反性:
。 - 对称性:若
,则 。 - 传递性:若
,则 。
- 自反性:
- 线性运算:若
,则有: 。 。
积性函数#
定义:若
欧拉函数
筛法#
埃拉托斯特尼筛法(埃氏筛)#
过程
考虑这样一件事情:对于任意一个大于 ,那么它的
如果我们从小到大考虑每个数,然后同时把当前这个数的所有(比自己大的)倍数记为合数,那么运行结束的时候没有被标记的数就是素数了。
vector<intprime;
bool is_prime[N];
void Eratosthenes(int n) {
is_prime[0]=is_prime[1]=0;
for(int i=2;i<=n;++i) is_prime[i]=true;
for(int i=2;i<=n;++i){
if (is_prime[i]){
prime.push_back(i);
if((long long)i*i>n) continue;
for(int j=i*i;j<=n;j+=i) is_prime[j]=false;
}
}
}
时间复杂度为
线性筛(欧拉筛)#
我们每次对于一个数,只选择其最小质因子进行标记,当
int pri[1000010];
bool isp[N],cnt=0;
void prime(int n){
memset(isp,1,sizeof(isp));
isp[1]=0;
for(int i=2;i<=n;++i){
if(isp[i]) pri[++cnt]=i;
for(int j=1;j<=cnt && i*pri[j]<=n;++j){
isp[i*pri[j]]=0;
if(i%pri[j]==0) break;
}
}
}
这样优化,时间复杂度降为
拓展
筛法可以处理欧拉函数
int pri[1000010];
bool isp[N],cnt=0;
int phi[1000010];
void prime(int n){
memset(isp,1,sizeof(isp));
isp[1]=0;
phi[1]=1;
for(int i=2;i<=n;++i){
if(isp[i]) pri[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt && i*pri[j]<=n;++j){
isp[i*pri[j]]=0;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
phi[i*pri[j]]=phi[i]*phi[pri[j]];
}
}
}
逆元#
定义
求法
- 拓展欧几里得法
void exgcd(int a, int b, int& x, int& y) {
if (b == 0) {
x = 1, y = 0;
return;
}
exgcd(b, a % b, y, x);
y -= a / b * x;
}
本质上是一个原理。
- 快速幂法
因为有
int qpow(long long a, int b) {
int ans = 1;
a = (a % p + p) % p;
for (; b; b >>= 1) {
if (b & 1) ans = (a * ans) % p;
a = (a * a) % p;
}
return ans;
}
- 线性求法(不会证,自己搜)
inv[1] = 1;
for (int i = 2; i <= n; ++i) {
inv[i] = (long long)(p - p / i) * inv[p % i] % p;
}
中国剩余定理(CRT)#
可求解如下形式的一元线性同余方程组(其中
上面的「物不知数」问题就是一元线性同余方程组的一个实例。
过程#
- 计算所有模数的积
; - 对于第
个方程:- 计算
; - 计算
在模 意义下的 逆元 ; - 计算
(不要对 取模)。
- 计算
- 方程组在模
意义下的唯一解为: 。
LL CRT(int k, LL* a, LL* r) {
LL n = 1, ans = 0;
for (int i = 1; i <= k; i++) n = n * r[i];
for (int i = 1; i <= k; i++) {
LL m = n / r[i], b, y;
exgcd(m, r[i], b, y); // b * m mod r[i] = 1
ans = (ans + a[i] * m * b % n) % n;
}
return (ans % n + n) % n;
}
作者:God_Max_Me
出处:https://www.cnblogs.com/lizihan00787/p/18685868
版权:本作品采用「God_Max_Me-非商业性使用」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!