刷了好几天的数论了
noip要考的几乎都刷了一遍
看着公式有生无可恋的感觉啊
下面是一些总结
1.组合数
去年的noip考了组合数递推公式
C(n, m) = C(n - 1, m - 1) + C(n - 1, m);
还有可以通过二项式定理推出来的几个结论
C(n, 0) + C(n, 1) + C(n, 2) + ... + C(n, n) = 2n
ΣC(n, i) = 2n - 1 (i 为基数或 i 为偶数)
2.(扩展)欧几里德算法
欧几里德算法
1 void gcd(ll a, ll b) { 2 return (b == 0) ? a : gcd(b, a % b); 3 }
扩展欧几里德算法
用于求不定方程 ,逆元啊等等
可以求出 ax + by = gcd (a, b) 的一组解 x, y,并且|x| + |y| 最小。
1 void exgcd(ll a, ll b, ll& d, ll& x, ll &y) { 2 if (!b) { d = a; x = 1; y = 0; } 3 else { exgcd(b, a % b, d, y, x); y -= x*(a/b); } 4 }
3.欧拉函数
φ(n) = n (1 - 1 / p1) (1 - 1 / p2) ... (1 - 1 / pk);
线性求欧拉函数
inline ll GetPhi(ll a) { ll res = a; for (int i = 2; i * i <= a; i++) if (a % i == 0) { res = res / i * (i - 1); while (a % i == 0) a /= i; } if (a > 1) res = res / a * (a - 1); return res; }
筛法求欧拉函数 (顺便可以求素数
ll phi[N + 10], p[N >> 1], tot; bool f[N] = {1, 1}; inline void GetPhi() { phi[1] = 1; for (int i = 2; i <= N; i++) { if (! f[i]){ p[tot++] = i; phi[i] = i - 1; } for (int j = 0; j < tot && p[j] * i <= N; j++) { f[p[j] * i] = true; if (i % p[j]) phi[i * p[j]] = phi[i] * (p[j] - 1); else phi[i * p[j]] = phi[i] * p[j]; } } }
3.费马小定理
这个应该都知道啦
ap - 1 ≡ 1 (mod p)
4.线性筛素数
int p[N], tot; inline void prime(int n) { f[0] = true; f[1] = true; for (int i = 2; i <= n; i++) { if (!f[i]) p[tot++] = i; for (int j = 0; j < tot && i * p[j] <= n; j++) { f[i * p[j]] = true; if (i % p[j] == 0) break; } } }
4.逆元
5.组合数取模(卢卡斯定理)
(待补充...)