数学基础
前言
又回来整理 前面学的都忘干净了...
大多数(或者是全部)定理只有结论 不涉及证明 代码如果可以的话后面会补充
由于不分篇目的原因 内容势必会非常杂乱 但是应该不会分开写了 反正也没人看
前面其实已经有数学基础1了 这是 2
写的原因是上一遍和没学差不多
所以有些东西是重复的
或许后面还会有 3
或者 4
什么的 也有可能继续在这个后面写
3
写不动了 受限于个人水平 有些东西学不会 理解能力跟不上了 所以开4了(雾
平衡三进制
对称三进制 不标准的计数体系 数字由 -1
, 0
, 1
构成 基数为 3
用 z
代替 -1
0 0
1 1
2 1Z
3 10
4 11
5 1ZZ
-1 Z
-2 Z1
-3 Z0
-4 ZZ
-5 Z11
负数即为将正数的数字倒转 负数最高位为 z
正数最高位为 1
转换
先将一个数表示为 3
进制 从最低位开始迭代 跳过任何的 0
和 1
遇到 2
时将其变为 z
下一位的数字加 1
遇到 3
变为 0
下一位数字加 1
平衡三进制具有唯一性
一些符号
([x]) 表示 (x) 下取整
(p_k) 表示第 (k) 个素数
(pi(x)) 表示 (1-)x 范围内的素数个数
(mu(x)) 表示莫比乌斯函数
(#S) 表示 (S) 集合的大小
(delta(x)) 表示 (x) 的最小质因子
(P^+(n)) 表示 (x) 的最大质因子
虽然并没有什么用就是了
素数
定义
如果一个数 除了 (1) 和它本身外 无其他因子 这个数被称为质数 否则称为合数
(1) 既不是素数也不是合数
质因数分解
定义 任何一个大于 (1) 的正整数都能被唯一分解为有限个质数的乘积 写作:
-
唯一分解定理
对于某一正整数 (n) 其质因数分解的方式是唯一的
-
正整数除法
将 被除数 与 除数 先进行质因数分解 再将对应每个素数的指数相减
有
若 (m mid n)
则 (n div m = p_1^{a_1 - b_1} p_2^{a_2 - b_2}...p_m^{a_m - b_m})
满足 (a_1 geq b_1, a_2 geq b_2 , ...)
验证 (n) 是否可以被 (m) 整除 比较两数质因数分解后的各项质数
素数判定
试除法
不断尝试小于 (x) 且大于 (1) 的自然数 只要有一个能整除 (x) 则 (x) 为合数 否则 (x) 是素数
由于约数都是成对存在的 所以只需尝试 ([1, sqrt x]) 即可
筛法求素数
埃氏筛
复杂度 (O(nlog ^2n))
对于枚举的数 枚举其倍数 并且将其倍数标记为合数
一个数会被其所有因子筛一遍 造成时间上的浪费 至于优化
欧拉筛(线筛)
复杂度 (O(n))
思路与埃筛基本相同 但是保证了每个数只被其最小质因子筛一遍 对于枚举的数 (i) 如果其之前没有被标记 将其即为质数 然后枚举其质数倍 将其倍数标记为合数 在 (i mod 第j个素数 = 0) 时 结束枚举
费马小定理
如果 (p) 为质数 有整数 (a) 且 (a ot p) 则 (a^{p - 1} equiv 1 mod p)
与欧拉定理的关系
当 (p) 为质数时
此时的欧拉定理可写为
即 费马小定理
费马小定理即欧拉定理中 (p) 为质数时的特殊情况
二次探测定理
若 (p) 为质数 且 (x^2 equiv 1 mod p)
那么 (x equiv 1 mod p) 和 (x equiv p - 1mod p) 中的一个成立
(p mid (x + 1)(x - 1))
约数
定义
如果 (a mid b) 则 (a) 为 (b) 的约数 (b) 为 (a) 的倍数
特别地 任何数都是 (0) 的约数
一般地 有 (1 mid a) 与 (a mid a) 则 (1), (a) 称 (a) 的平凡因子
约数的几种求法
-
试除法
枚举 ([1, sqrt n]) 中所有整数 进行试除 判断 (n) 能否整除
-
优化
当求 ([1, n]) 中所有数的约数时 上面的试除法复杂度就变成了 (O(n sqrt n))
(1) 到 (n) 中一一个数 (x) 为约数的数 (x, 2x, 3x, ..., lfloor frac nx floor imes x) 枚举到 (x) 的时候 枚举 (x) 的倍数 使他们的约数加上一个 (x)
复杂度 (O(nlog n))
对任意数 (n) 求约数个数
根据 (n = p_1^{c_1}p_2^{c_2}...p_m^{c_m})
通项公式: (num = sum_{i = 1}^m(c_i + 1))
对任意数 (n) 求约数和
通项公式: (sum = prod_{i = 1}^msum_{j = 0}^{c_i}p_i^j)
最大公约数 与 最小公倍数
最大公约数
定义 : 有 (n), (m) 两整数 (n, m) 的最大公约数 (d) 满足 (d mid n) 且 (d mid m) 的最大的 (d) 记作 (d = gcd(n, m)) 简写为 ((n, m))
设 (n = p_1^{a_1}p_2^{a_2}...p_k^{a_k}, m = p_1^{b_1}p_2^{b_2}...p_k^{b_k})
则 (d = p_1^{min {a_1, b_1 }}p_2^{min {a_2, b_2 }}...p_k^{min {a_k, b_k }})
最小公倍数
定义 : 有 (n), (m) 两整数 (n, m) 的最小公倍数 (l) 满足 (n mid l) 且 (m mid l) 的最小的 (l) 记作 (l = lcm(n, m)) 简写为 ([n, m])
(l = d = p_1^{max {a_1, b_1 }}p_2^{max {a_2, b_2 }}...p_k^{max {a_k, b_k }})
另 有 ((n, m) imes [n, m] = nm)
互质
定义 : 若 (gcd(a, b) = 1) 称 (a, b) 互质 记为 (a ot b)
即: 当 (a, b) 进行质因数分解之后 没有相等的质因数
性质 :
- 对于两个不同的质数 (m, n) 有 (gcd(n, m) = 1)
- 对于任意相邻的整数 (n, m) 有 (gcd(n, m) = 1)
- 对任意自然数 (n) 有 (gcd(n, 1) = 1)
- 一个质数 (m) 和一个合数 (n) 若 (m mid n) 则 (gcd(n, m) = 1)
欧拉函数
定义 : 对正整数 (n) 满足 (a ot n) (a < n) 的 (a) 的个数 即为 (n) 的欧拉函数的值 记作 (varphi(n))
性质:
- (varphi(1) = 1)
- (varphi(p) = p - 1)
- 若 (n ot m) 则 (varphi(nm) = varphi(n)varphi(m))
- 当 (n) 为奇数 (varphi(2n) = varphi(n))
- (varphi(p^a) = p^a(1 - frac 1p))
- 对任意大于 (1) 的正整数 (n) 有(varphi(n) = nprod_{i = 1}^n(1 - frac 1{p_i}))
对 5 :
比 (p^a) 小的数有 (p^a - 1) 个 与 (p^a) 不互质的数 一定是 (p) 的倍数 (p) 的倍数可以表示为 (tp, t in [1, p_{a - 1} - 1])
与 (p) 互质的数的个数:
(varphi(p^a) \ = (p^a - 1) - (p^{a - 1} - 1) \ = p^a - p^{a - 1} \ = p^{a - 1}(p - 1) \ = p^a(1 - frac 1p))
对 6 :
设 (n = p_1^{c_1}p_2^{c_2}...p_k^{c_k})
(varphi(n) \ = varphi(p_1^{c_1}p_2^{c_2}...p_k^{c_k}) \ = varphi(p_1^{c_1})varphi(p_2^{c_2})...varphi(p_k^{c_k}) \ = p_1^{c_1}(1 - frac 1{p_1})p_2^{c_2}(1 - frac 1{p_2})...p_k^{c_k}(1 - frac 1{p_k}) \ = (p_1^{c_1}p_2^{c_2}...p_k^{c_k}) imes (1 - frac 1{p_1})(1 - frac 1{p_2})...(1 - frac 1{p_k}) \ = nprod_{i - 1}^n(1 - frac 1{p_i}))
欧拉函数筛(咕)
众所周知 有个叫欧拉函数筛的东西 还有欧拉线筛 可以在筛质数的时候顺便筛一下欧拉函数 这里先咕着 后面补
记着这个在 1 里面是有的
欧拉定理
对于两个互质的数 (a, p) 有 (a^{varphi(p)} equiv 1 mod p)
关于同余的一些概念
- 反身性: (a equiv a mod m)
- 对称性: 若 (a equiv b mod m) 则 (b equiv a mod m)
- 传递性: 若 (a equiv b mod m) 且 (b equiv c mod m) 则 (a equiv c mod m)
- 若 (a equiv b mod m, c equiv d mod m) 则 (a pm c equiv b pm d mod m)
- 若 (a equiv b mod m, c equiv d mod m) 则 (ac equiv bd mod m)
- 若 (a equiv b mod m, n in N) 则 (a^n equiv b^n mod m)
- 若 (ac equiv bd mod m) 则 (a equiv b mod frac m{(c, m)}) 当 ((c, m) = 1) 时 (a equiv b mod m)
- 若 (a equiv b mod m_i, i = 1, 2, ..., k) 则 (a equiv b mod [m_1, m_2, ..., m_k])
欧几里得与扩展欧几里得
欧几里得定理
(gcd(a, b) = gcd(b, a \% b)) 当 (b = 0) 时 有 (gcd(a, b) = |a|)
应用: 可以方便的求 ((a, b))
int gcd(int a, int b) {return b ? gcd(b, a % b) : a;}
裴蜀定理
设 (a, b) 为不全为 (0) 的整数 则存在 (x, y) 使 (ax + by = gcd(a, b))
特别的 当 (gcd(a, b) = 1) 则 存在 (x, y) 使 (ax + by = 1)
题目: 裴蜀定理
大概是定理的推广形式
代码
/*
Time: 6.19
Worker: Blank_space
Source: P4549 【模板】裴蜀定理
*/
/*--------------------------------------------*/
#include<cstdio>
#define Abs(x) ((x) < 0 ? -(x) : (x))
/*--------------------------------------头文件*/
int n, ans;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
int gcd(int _a, int _b) {return _b ? gcd(_b, _a % _b) : _a;}
/*----------------------------------------函数*/
int main() {
n = read(); ans = read(); ans = Abs(ans);
for(int i = 2, x; i <= n; i++) x = read(), ans = gcd(ans, Abs(x));
printf("%d", ans);
return 0;
}
扩展欧几里得
对于不完全为 (0) 的两个数 (a, b) 必然存在无数个 (x, y) 使方程 (ax + by = gcd(a, b)) 成立
求特殊解:
void exgcd(int a, int b, int &d, int &x, int &y) {
if(b) exgcd(b, a % b, d, y, x), y -= x * (a / b);
else d = a, x = 1, y = 0;
}
应用:
- 求解不定方程
- 求解同余方程
- 求解模的逆元
- 求解同余方程组
对 1:
对方程 (ax + by = c)
不定方程 (ax + by = gcd(a, b)) 有无数组解
若 (gcd(a, b) mid c) 则原方程无解
若 (gcd(a, b) mid c) 设 (d = gcd(a, b))
原方程可转化为 (a(x imes frac dc) + b(y imes frac dc) = c imes frac dc)
令 (x_1 = x imes frac dc, y_1 = y imes frac dc) 得
(ax_1 + by_1 = d) 求解该方程得 (x_1, y_1)
得: (x = x_1 imes frac cd, y = y_1 imes frac cd)
既得原方程的解
对 2:
(ax equiv c mod b o ax + nb = c + mb)
有 (ax + (n - m)b = c) 求解该不定方程所得 (x) 即为原方程的解
但是这不一定是最小正整数解
x = (x + b) % b;
题目: 同余方程
代码
/*
Time: 6.19
Worker: Blank_space
Source: P1082 [NOIP2012 提高组] 同余方程
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------文件*/
int a, b, d, x, y;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void exgcd(int _a, int _b, int &_d, int &_x, int &_y) {
if(_b) exgcd(_b, _a % _b, _d, _y, _x), _y -= _x * (_a / _b);
else _d = _a, _x = 1, _y = 0;
}
/*----------------------------------------函数*/
signed main() {
a = read(); b = read(); exgcd(a, b, d, x, y); x /= d; printf("%lld", (x % b + b) % b);
return 0;
}
对 3:
适用于模数不为质数的情况
即解: (x imes inv(x) equiv 1 mod p)
令 (a = x, x = inv(x)) 有 (ax equiv 1 mod p)
对 4:
解如下方程组:
(egin{cases}x equiv a_1 mod b_1 \ x equiv a_2 mod b_2 \ ... \ x equiv a_n mod b_n end{cases})
其中 (a, b) 为非负整数 不保证模数互质
求解:
使用 (exgcd) 对同余方程进行合并
假设当前已经求出了前 (k - 1) 个方程的解 (x_{k - 1}) 设 (M = lcm_{i = 1}^{k - 1}b_i)
即前 (k - 1) 个方程的通解为 (x_{k - 1} + tM) 现在目标是使第 (k) 个方程的解为前 (k - 1) 个方程的通解的同时也满足第 (k) 个方程的条件 设 (x_k = x_{k - 1} + tM) 有 (x_{k - 1} + tM equiv a_k mod b_k) 显然 该方程是可解的 得 (t) 的值 则可求 (x_k = x_{k - 1} + tM) 经过 (n) 次操作后 即得原方程组的解
代码:(数据较大 龟速乘)
/*
Time: 6.19
Worker: Blank_space
Source: P4777 【模板】扩展中国剩余定理(EXCRT)
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------文件*/
int n, M, ans, d, x, y;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
int mul(int _a, int _b, int mod, int res = 0) {for(; _b; _a = (_a + _a) % mod, _b >>= 1) if(_b & 1) res = (res + _a) % mod; return res;}
void exgcd(int _a, int _b, int &_d, int &_x, int &_y) {
if(_b) exgcd(_b, _a % _b, _d, _y, _x), _y -= _x * (_a / _b);
else _d = _a, _x = 1, _y = 0;
}
/*----------------------------------------函数*/
signed main() {
n = read(); M = read(); ans = read();
for(int i = 2; i <= n; i++)
{
int b = read(), a = read(); a = ((a - ans) % b + b) % b;
exgcd(M, b, d, x, y); if(a % d) {puts("-1"); return 0;}
x = mul(x, a / d, b); ans += x * M; M = M / d * b; ans = (ans % M + M) % M;
}
printf("%lld", ans);
return 0;
}
乘法逆元
对于在模意义下的除法 对模数 (p) 和除数 (x) 往往可以找到一个特殊的数 (y) 用 $ imes y$ 代替 (div x) 将 (y) 记作 (x) 的逆元 记作 (inv(x))
通过定义: (x imes inv(x) equiv 1 mod p)
求解逆元
这里本来有四种方法 但是由于太懒 所以变成了三种
-
费马小定理
只适用于模数为质数的情况 这是最常用的一种 因为大多数题目的模数都会设为质数(不是刻意卡的话)
费马小定理: (x^{p - 1} equiv 1 mod p)
故有: (x^{p - 1} equiv x imes inv(x) mod p)
两侧同除 (x) 有: (inv(x) equiv x^{p - 2} mod p)
所以快速幂直接求 ((x^{p - 2}) \% p) 即为 (div x) 模 (p) 意义下的逆元
-
递推
只适用于模数为质数的情况 如果要求的逆元数量很多而且连续 就可以使用递推
(inv(i) = -lfloor frac pi floor imes inv(p \% i) \% p)
正确性:
设 (p = ik + r)
有 (p equiv 0 mod p)
故 (ik + r equiv 0 mod p)
两边同乘 (inv(i)inv(r))
有 (i imes inv(i) imes k imes inv(r) + r imes inv(r) imes inv(i) equiv 0 mod p) 化简 得 (k imes inv(r) + inv(i) equiv 0 mod p)
故 (inv(i) equiv -k imes inv(r) mod p)
即 (inv(i) equiv -lfloor frac pi floor imes inv(p \% i) mod p)
但是是求最小正整数解 加个 (p) 调一下
即 (inv(i) = (p - lfloor frac pi floor) imes inv(p \% i) \% p)
-
扩展欧几里得
模数可以不为质数
由逆元的定义 (x imes inv(x) equiv 1 mod p)
把这个东西当做同余方程来解就好了
题目: 乘法逆元
这个题目适合用线性求逆元
代码
/*
Time: 6.19
Worker: Blank_space
Source: P3811 【模板】乘法逆元
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
const int C = 1e6 + 7;
/*------------------------------------常量定义*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------文件*/
int n, p, inv[C << 2];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
/*----------------------------------------函数*/
signed main() {
n = read(); p = read(); inv[1] = 1;
for(int i = 2; i <= n; i++) inv[i] = (p - p / i) * inv[p % i] % p;
for(int i = 1; i <= n; i++) printf("%lld
", inv[i]);
return 0;
}
题目: 有理数取余
看一眼 高精!?
高个鬼 要模数干啥的
费马小定理的写法
代码
/*
Time: 6.19
Worker: Blank_space
Source: P2613 【模板】有理数取余
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
const int mod = 19260817;
/*------------------------------------常量定义*/
int a, b;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = ((x << 3) + (x << 1) + (ch ^ 48)) % mod; ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
int power(int _a, int _b, int res = 1) {for(; _b; _a = _a * _a % mod, _b >>= 1) if(_b & 1) res = res * _a % mod; return res;}
/*----------------------------------------函数*/
signed main() {
a = read(); b = read(); printf("%lld", a * power(b, mod - 2) % mod);
return 0;
}
//话说为什么这个代码能过啊...
//感觉数据范围会炸的可以看一眼快读
//数据里面好像并没有无解的数据点
扩展欧几里得的写法
代码
/*
Time: 6.19
Worker: Blank_space
Source: P2613 【模板】有理数取余
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
const int mod = 19260817;
/*------------------------------------常量定义*/
int a, b, d, x, y;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = ((x << 3) + (x << 1) + (ch ^ 48)) % mod; ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void exgcd(int _a, int _b, int &_d, int &_x, int &_y) {
if(_b) exgcd(_b, _a % _b, _d, _y, _x), _y -= _x * (_a / _b);
else _d = _a, _x = 1, _y = 0;
}
/*----------------------------------------函数*/
signed main() {
a = read(); b = read(); exgcd(b, mod, d, x, y); x /= d; x = (x % mod + mod) % mod; printf("%lld", a * x % mod);
return 0;
}
扩展欧拉定理
模 (p) 意义下 对于 (a^b) 有
(a^b equiv egin{cases}a^b & b < varphi(p) \ a^{b mod varphi(p) + varphi(p)} & b geq varphi(p) end{cases})
众所周知 有一个叫欧拉筛的东西 虽然对这个题并没有什么用
题目: 扩展欧拉定理
很惊喜的发现 (b) 后面跟着一大坨令人恶心的东西 然后又发现直接筛欧拉函数复杂度就会爆炸 但是这里只需要求一个数的欧拉函数值 根据前面 (varphi(n) = nprod(1 - frac 1{p_i})) 考虑对 (n) 质因数分解 直接试除
代码
/*
Time: 6.19
Worker: Blank_space
Source: P5091 【模板】扩展欧拉定理
*/
/*--------------------------------------------*/
#include<cstdio>
#define int long long
/*--------------------------------------头文件*/
const int INF = 1e14;
/*------------------------------------常量定义*/
inline void File() {
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
/*----------------------------------------文件*/
int a, b, m, phi = INF, ans = 1;
bool flag;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {
x = (x << 3) + (x << 1) + (ch ^ 48);
if(x >= phi) flag = 1, x %= phi; ch = getchar();
}
return x * f;
}
/*----------------------------------------快读*/
int power(int _a, int _b, int res = 1) {for(; _b; _a = _a * _a % m, _b >>= 1) if(_b & 1) res = res * _a % m; return res;}
/*----------------------------------------函数*/
signed main() {
a = read(); m = read(); phi = m; int tmp = m;
for(int i = 2; i * i <= m; i++) if(!(tmp % i))
{
phi -= phi / i;
while(!(tmp % i)) tmp /= i;
}
if(tmp > 1) phi -= phi / tmp; b = read() + flag * phi;
printf("%lld", power(a, b));
return 0;
}
题目: 上帝与集合的正确用法(待完成)