数论

最大公约数

欧几里得算法求gcd

\(设 a > b, 且a = b × q + r,r < b\)
\(则\textit{gcd(a, b) = gcd(b, a % b)}\)

code
int gcd(int a, int b)
{
    return !b ? a : gcd(b, a % b);
}

扩展欧几里得算法(exgcd)

常用于求 \(ax + by = gcd(a, b)\) 的一组可行解

code
int exgcd(int a, int b, int &x, int &y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

组合数

  • 定义:从 \(n\) 个不同元素中,任取 \(m(m≤n)\) 个元素并成一组,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的一个组合;从 \(n\) 个不同元素中取出 \(m(m≤n)\) 个元素的所有组合的个数,叫做从 \(n\) 个不同元素中取出 \(m\) 个元素的组合数.
  • 公式: \(C_{n}^{m}=\frac{n!}{m!(n - m)!}\)

递推求组合数

code
for (int i = 0; i <= n; i ++ )
{
    c[i][i] = c[i][0] = 1;
    for (int j = 1; j < i; j ++ )
        c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
}

Lucas定理求组合数

\(\textit{C(n,m)%p=C(n/p,m/p)*C(n%p,m%p)%p}\)
\((p为质数)\)

code1
int qmi(int a, int k)
{
    int res = 1;
    while (k)
    {
        if (k & 1) res = (ll) res * a % mod;
        a = (ll) a * a % mod;
        k >>= 1;
    }
    return res;
}

int C(int a, int b)
{
    int res = 1;
    for (int i = 1, j = a; i <= b; i ++, j -- )
    {
        res = (ll) res * j % mod;
        res = (ll) res * qmi(i, mod - 2) % mod;
    }
    return res;
}

int lucas(ll a, ll b)
{
    if (a < mod && b < mod) return C(a, b);
    return (ll)C(a % mod, b % mod) * lucas(a / mod, b / mod) % mod;
}
code2
int qmi(int a, int k)
{
    int res = 1;
    while (k)
    {
        if (k & 1) res = (ll) res * a % mod;
        a = (ll) a * a % mod;
        k >>= 1;
    }
    return res;
}
 
void init()
{
    c[0] = 1;
    for (int i = 1; i <= n; i ++ )
    c[i] = c[i - 1] * i % mod;
}
 
int C(int a, int b)
{
    return c[a] * qmi(c[b] * c[a - b] % mod, mod - 2) % mod;
}
 
int lucas(ll a, ll b)
{
    if (a < mod && b < mod) return C(a, b);
    return (ll)C(a % mod, b % mod) * lucas(a / mod, b / mod) % mod;
}

同余

中国剩余定理 CRT

求解如下形式的一元线性同余方程组(其中 \(n_1, n_2, ···, n_k\) 两两互质)
\( \left\{ \begin{matrix} x & \equiv & a_1 & (mod \ n_1)\\ x & \equiv & a_2 & (mod \ n_2)\\ \vdots\\ x & \equiv & a_k & (mod \ n_k) \end{matrix} \right. \)

code
int CRT(int k, int *a, int *r)
{
    int M = 1, ans = 0;
    for (int i = 1; i <= k; i ++ ) M = M * r[i];
    for (int i = 1; i <= k; i ++ )
    {
        int m = M / r[i], b, y;
        exgcd(m, r[i], b, y);
        ans = (ans + a[i] * m * b % M) % M;
    }
    return (ans % M + M) % M;
}

拓展中国剩余定理 exCRT

质数

  • 质数:只有两个正因数(1和自己)的自然数即为质数.比1大但不是素数的数称为合数.1和0既非素数也非合数.

性质

  • \(N\) 以内的素数的个数随着N的增大趋近于 \(log(n)\).
  • 从不大于 \(n\) 的自然数随机选一个数,它是素数的概率大约是 \(1/In n\)(素数定理).
  • 随着 \(n\) 的增大素数越来越稀疏.
  • 在一个大于 \(1\) 的数 \(a\) 和它的2倍之间(即区间 \((a,2a]\) 中)必存在至少 \(1\) 个素数.

线性筛(欧拉筛法)

code
int primes[N], cnt;
bool st[N];

void prime(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i]) primes[ ++ cnt] = i;
        for (int j = 1; j <= cnt && primes[j] * i <= n; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}

欧拉定理 & 费马小定理

欧拉函数

定义

欧拉函数,即 \(\varphi(n)\),表示的是小于等于 \(n\)\(n\) 互质的数的个数。

性质

  • 欧拉函数是积性函数。

  • 特别地,当 n 是奇数时 \(\varphi(2n) = \varphi(n)\)

  • \(n = \sum_{d \mid n}{\varphi(d)}\)

  • \(n = p^k\),其中 \(p\) 是质数,那么 \(\varphi(n) = p^k - p^{k - 1}\)。 (根据定义可知)

  • 由唯一分解定理,设
    n = \(\prod_{i=1}^{s}p_i^{k_i}\),其中 \(p_i\) 是质数,有
    \(\varphi(n) = n \times \prod_{i = 1}^s{\dfrac{p_i - 1}{p_i}}\)

求欧拉函数

code
int phi(int x)
{
    if (x == 1) return 1;
    int res = x;
    for (int i = 2; i * i <= x; i ++ )
    {
        if (x % i != 0) continue;
        while (x % i == 0) 
            x /= i;
        res = res / i * (i - 1);
    }
    if (x != 1) res = res / x * (x - 1);
    return res;
}

线性筛欧拉函数

code
const int N = 3e8;

int primes[N], cnt;
bool st[N];
int phi[N];

void prime_phi(int n)
{
    phi[1] = 1;
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i])
        {
            primes[ ++ cnt] = i;
            phi[i] = i - 1;
        }
        for (int j = 1; primes[j] * i <= n && j <= cnt; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0)
            {
                phi[primes[j] * i] = phi[i] * primes[j];
                break;
            }
            phi[primes[j] * i] = phi[i] * (primes[j] - 1);
        }
    }
}

欧拉定理

定义

\(\gcd(a, m) = 1\),则 \(a^{\varphi(m)} \equiv 1 \pmod{m}\)

扩展欧拉定理

定义

\( a^b \equiv \begin{cases} a^{b \bmod \varphi(m)}, &\gcd(a,m) = 1, \\ a^b, &\gcd(a,m)\ne 1, b < \varphi(m), \\ a^{(b \bmod \varphi(m)) + \varphi(m)}, &\gcd(a,m)\ne 1, b \ge \varphi(m). \end{cases} \pmod m\)

  • 解释
    第二行表达的意思是:如果 \(b < \varphi(m)\) 的话,就不能降幂了。
    原因是因为题目中 \(m\) 不会太大,而如果 \(b < \varphi(m)\),自然复杂度是可以接受的。而如果 \(b \ge \varphi(m)\) 的话,复杂度可能就超出预期了,这个时候我们才需要降幂来降低复杂度。

费马小定理

定义

\(p\) 为素数,\(\gcd(a, p) = 1\),则 \(a^{p - 1} \equiv 1 \pmod{p}\)

另一个形式:对于任意整数 \(a\),有 \(a^p \equiv a \pmod{p}\)

高斯消元

code
const int N = 80;
const db eps = 1e-6;

int n;
db gs[N][N];

void gauss()
{
    for (int i = 0; i < n; i++)
    {
        int pos = i;
        for (int j = i + 1; j < n; j++)
            if (fabs(gs[j][i]) > fabs(gs[pos][i]))
                pos = j;
        swap(gs[i], gs[pos]);
        for (int j = 0; j < n; j++)
        {
            if (i == j)
                continue;
            double div = gs[j][i] / gs[i][i];
            for (int k = i; k <= n; k++)
                gs[j][k] -= gs[i][k] * div;
        }
    }
    for (int i = 0; i < n; i++)
        gs[i][n] /= gs[i][i];
}

数论函数

积性函数

若有一函数 \(f\), 对于 \(\forall x, y \in S\) 使得 \(x \times y \in S, f(x)f(y) = f(xy)\), 则称 \(f\)\(S\)具有积性,也称 \(f\)\(S\) 下的 积性函数.

定义

  • 完全积性函数:若函数 \(f\) 在实数域 \(R\) 下具有积性,则我们称 \(f\) 具有 完全积性,称 \(f\)完全积性函数.完全积性函数属于积性函数.

  • 不完全积性函数 :若有一函数 \(f\) , 不存在集合 \(S\) 使得 \(f\)\(S\) 下的积性函数,但存在二元组 \(<x, y>\) 使得
    \(f ( x ) f ( y ) = f ( x y )\) 成立,则我们称 \(f\) 为不完全积性函数.
    不完全积性函数属于积性函数.

  • 性质:若 \(f, g\) 均为积性函数,则 \(f\cdot g\) 也是积性函数.

数论函数

  • 指示函数: \(I(x) = 1\), 具有完全积性.
  • 幂函数: \(Id_k(n) = n^k\), 具有完全积性.
  • 单位函数 : \(\varepsilon(x) = [x == 1]\) , 整数域下有积性.
  • 莫比乌斯函数: \(\mu(x)\), \(\mu \times I = \varepsilon\).
  • 欧拉函数 : \(\varphi(x)\)小于 \(x\) 并与 \(x\) 互质的数的个数.
  • 除数函数: \(\sigma_k(x) = \sum _{d|n}d^k\), 当 \(k = 1\) 时为因数和函数 \(\sigma(x)\) , 当 \(k = 0\) 时为因数个数函数 \(\sigma_0(x)\).

迪利克雷(Dirichlet)卷积

一种二元运算,定义为:

\((f\times g)(n) = \sum_{xy=n} f(x)g(y)\)

等价于

\((f\times g)(n) = \sum_{d|n} f(d)g(\frac{n}{d})\)

性质

1、交换律\((f\times g)(x) = (g\times f)(x)\).

2、结合律\((f\times g \times h)(x) = (f \times (g \times h))(x)\).

3、加法分配律\(((f + g) \times h)(x) = (f \times h + g \times h)(x)\)

4、单位元\((\varepsilon \times f)(n) = \sum _{d|n}\varepsilon(d)f(\frac{n}{d}) = f(n)\) (注意仅在 \(d=1\)\(\varepsilon (n)\) 不等于 \(0\)).

所以单位函数 \(\varepsilon\) 是狄利克雷卷积的单位元.

5、逆元 :假设 \(f \times g = \varepsilon\) , 则称 \(g\)\(f\) 的迪利克雷逆元(Dirichlet inverse), 记作 \(f^{-1}\) ,必要条件\(f(1)\ne 0\).

对于 \(g = f^{-1}\) 的一个递归定义如下:

\(g(n) = \left\{\begin{matrix}\frac{1}{f(n)}, &n=1 \\-\frac{1}{f(1)}\sum _{d|n,d>1} f(d)g(\frac{n}{d}),&n \ne 1\end{matrix}\right.\)

莫比乌斯反演

矩阵

矩阵快速幂

code
struct Matrix
{
    int a[N][N];

    Matrix()
    {
        memset(a, 0, sizeof a);
    }

    Matrix operator * (const Matrix &b) const
    {
        Matrix res;
        int r;
        for (int i = 1; i <= n; i ++)
            for (int k = 1; k <= n; k ++ )
            {
                r = a[i][k];
                for (int j = 1; j <= n; j ++ )
                res.a[i][j] = (res.a[i][j] + r * b.a[k][j]) % mod;
            }
        return res;
    }
}ans, base;

void qmi(int k)
{
    while (k)
    {
        if (k & 1) ans = ans * base;
        base = base * base;
        k >>= 1;
    }
}
posted @ 2022-08-02 18:14  kroyosh  阅读(44)  评论(0)    收藏  举报