数论总结 (常用定理+ 模板)

刷了好几天的数论了

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.组合数取模(卢卡斯定理)

(待补充...)

原文地址:https://www.cnblogs.com/cminus/p/7305917.html