1.欧几里得算法(GCD)
1.1 普通数的GCD
表达式
gcd(a,b)=gcd(b,a%b)代码实现
//非递归 int gcd(int a, int b) { for (int c = a%b; c != 0; c = a%b) a = b, b = c; return b; }
复杂度: O(log(n))
1.2 高精度的GCD
表达式
gcd(a,b)=gcd(a−b,b)gcd(2⋅a,b)=gcd(a,b)gcd(2⋅a,2⋅b)=gcd(a,b)复杂度: O(log(a)+log(b))
2.扩展欧几里得算法(exGCD)
方程形式:
aX+bY=gcd(a,b)求解方法:
设
a⋅X1+b⋅Y1=gcd(a,b)b⋅X2+(a%b)⋅Y2=gcd(b,a%b)其中
gcd(a,b)=gcd(b,a%b)a%b=a−(a/b)⋅b整理可得
a⋅X1+b⋅Y1=b⋅X2+(a−(a/b)⋅b)⋅Y2a⋅X1+b⋅Y1=a⋅Y2+b⋅[X2−(a/b)]⋅Y2所以
X1=Y2Y1=X2−(a/b)⋅Y2代码实现:
//递归 void exGcd(int a, int b, int &x, int &y) { if (b == 0) { x = 1; y = 0; return; } exGcd(b, a%b, x, y); int t = x; x = y; y = t-a/b*y; }
3.裴蜀定理
推论:
设 gcd(a1,a2,a3...an)=d
存在 X1,X2,X3...Xn
使得 ∑ni=1ai⋅Xi=d
求解方法:
先求 a1⋅X1+a2⋅X2=gcd(a1,a2)
再将 gcd(a1,a2) 带回原式,反复迭代就可得解
4.数论筛法
4.1 Eraosthens筛法
代码实现
void getPrime(const int n, int *p) { int tot = 0; memset(vis, 0, sizeof(vis)); for (int i = 2; i <= n; i++) { if (vis[i]) continue; p[++tot] = i; for (int j = 2; i*j <= n; j++) vis[i*j] = 1; } }
- 复杂度: O(n log n)
4.2 Euler筛法:
详情请百度 贾志鹏_线性筛法与积性函数.
代码实现
void getPrime(const int n, int *p) { int tot = 0; memset(vis, 0, sizeof(vis)); for (int i = 2; i <= n; i++) { if (!vis[i]) p[++tot] = i; for (int j = 1; j <= tot; j++) { if (i*p[j] > n) break; vis[i*p[j]] = 1; if (i%p[j] == 0) break; } } }
- 复杂度: O(n)
5.素数测试
5.1 Miller-Rabin算法
填坑
5.2 二次探测
我都不会
6.质因数分解
6.1 暴力分解法
代码实现
自行脑补复杂度: O(sqrt(n))
6.2 Pollard-Rho 椭圆曲线分解法
连怎么读我都不会
7.快速幂
代码实现
int pow(int a, int b, int p) { int ret = 1; while (b) { if (b & 1) ret = (ret*a)%p; a = (a*a)%p; b >>= 1; } return ret; }
复杂度: O(log(b))
8.积性函数
8.1 定义(引用)
在非数论的领域,积性函数指所有对于任何a,b都有性质f(ab)=f(a)f(b)的函数。
在数论中的积性函数:对于正整数n的一个算术函数 f(n),若f(1)=1,且当a,b互质时f(ab)=f(a)f(b),在数论上就称它为积性函数。
若对于某积性函数 f(n) ,就算a, b不互质,也有f(ab)=f(a)f(b),则称它为完全积性的。
8.2 重要的我知道的积性函数
φ(n) _欧拉函数
定义
φ(n)= 比 n 小且与
n 互质的正整数的数目.计算
详情请见 wikipedia
φ(n)=∏i=1rpki−1i(pi−1)=n∏p|n(1−1p)
μ(n) _莫比乌斯函数
定义
智商捉急只能打成这样μ(n)=⎧⎩⎨⎪⎪1(−1)k0n=1n=p1p2...pkother简单来说就是如果 n=1 则为 1 ,如果有平方因子就为
0 ,否则就是 (−1)k , k 是因数的个数。