数论总结

数论

1.1 Lucas定理 (扩展Lucas定理)【组合数取模】

Lucas定理:

要计算 C n m % p C_n^m \%p Cnm%p的值
n = n k p k + n k − 1 p k − 1 + . . . + n 1 p + n 0 n = n_kp^k+n_{k-1}p^{k-1}+...+n_1p+n_0 n=nkpk+nk1pk1+...+n1p+n0

m = m k p k + m k − 1 p k − 1 + . . . + m 1 p + m 0 m = m_kp^k+m_{k-1}p^{k-1}+...+m_1p+m_0 m=mkpk+mk1pk1+...+m1p+m0

C n m = ∏ i = 0 k C n i m i ( m o d   p ) C_n^m = \prod^k_{i = 0}C_{n_i}^{m_i}(mod\ p) Cnm=i=0kCnimi(mod p)

即将n.m分解为p进制,然后求每一位上的组合数,再乘起来,就是答案

  • 1、当n,m都很小的时候可以利用杨辉三角直接求。
  • C ( n , m ) = C ( n − 1 , m ) + C ( n − 1 , m − 1 ) C(n,m)=C(n-1,m)+C(n-1,m-1) C(n,m)=C(n1,m)+C(n1,m1)
  • 2、n和m较大,但是p为素数的时候,递归求解:
  • L u c a s ( n , m ) % p = L u c a s ( n / p , m / p ) ∗ C ( n % p , m % p ) % p Lucas(n,m) \%p = Lucas(n/p,m/p) * C(n\%p,m\%p)\%p Lucasn,m)%p=Lucas(n/p,m/p)C(n%p,m%p)%p
  • 递归出口:m=0时返回1
  • p较小时,可以预处理阶乘
LL qpow(LL a, LL b, LL p)//快速幂取模
{
    LL ans = 1;
    a %= p;
    while(b)
    {
        if(b & 1)
        {
            ans = ans * a % p;
            b--;
        }
        b >>= 1;
        a = a * a % p;
    }
    return ans;
}

LL inv(LL a, LL p)//求逆元,要求p为素数,且a和m互质
{
    return qpow(a, p - 2, p);
}

LL C(LL n, LL m)//求组合数
{
    if(m > n) 
        return 0;
    LL ans = 1;
    for(int i = 1; i <= m; i++)
    {
        LL a = (n + i - m) % p;
        LL b = i % p;
        ans = ans * (a * inv(b, p) % p) % p;
    }
    return ans;
}

LL Lucas(LL n, LL m)//求组合数取模
{
    if(m == 0) return 1;
    return C(n % p, m % p) * Lucas(n / p, m / p) % p;
}

//打表预处理组合数,可以加快阶乘计算
void getfac(int p)//阶乘表
{
    fac[0] = fac[1] = 1;
    for(int i = 2 ; i <= p; i++)
        fac[i] = fac[i - 1] * i % p;
}

LL C(LL n, LL m, LL p) //组合数
{
    if(m > n)
        return 0;
    else
        return fac[n] * inv(fac[m] * fac[n - m], p) % p;
}
  • n,m较大且p不为素数的时候,扩展Lucas定理

  • p = p 1 k 1 ∗ p 2 k 2 ∗ . . . ∗ p q k q p=p_1^{k_1}*p_2^{k_2}*...*p_q^{k_q} p=p1k1p2k2...pqkq p i p_i pi是质数)

  • 列出同余方程组 { a n s ≡ c 1   m o d   p 1 k 1 a n s ≡ c 2   m o d   p 2 k 2 . . . . . . a n s ≡ c n   m o d   p n k n \begin{cases} ans \equiv c_1 \ mod \ p_1^{k_1} \\ ans \equiv c_2 \ mod \ p_2^{k_2} \\...... \\ans \equiv c_n \ mod \ p_n^{k_n} \end{cases} ansc1 mod p1k1ansc2 mod p2k2......anscn mod pnkn

  • 其中 c i . . . c q c_i...c_q ci...cq是对于每一个 C n m % p i k i C_n^m \% p_i^{k_i} Cnm%piki求出的答案

  • 使用中国剩余定理即可求出ans。

  • 其中 C n m % p i k i C_n^m \% p_i^{k_i} Cnm%piki的求法关键在于 n ! % p i k i n! \% p_i^{k_i} n!%piki的求法,以下给出解法:

    1. n ! % p i k i n! \% p_i^{k_i} n!%piki是三部分的乘积
    2. 第一部分是 p i ⌊ n p i ⌋ p_i^{\lfloor \frac{n}{p_i} \rfloor} pipin
    3. 第二部分是 ⌊ n p i ⌋ ! \lfloor \frac{n}{p_i} \rfloor ! pin!
    4. 第三部分是上面的数之外的其他数(不超过 p i k i p_i^{k_i} piki)的乘积,可暴力
  • m ! % p i k i m! \% p_i^{k_i} m!%piki ( n − m ) ! % p i k i (n-m)! \% p_i^{k_i} (nm)!%piki的结果可能与 p i k i p_i^{k_i} piki不互质,无法求逆元,所以要先去除其中的质因子 p i p_i pi,求出逆元后,再乘回去。

  • 计算 n ! n! n!中的质因子p的个数x: x = ⌊ n p ⌋ + ⌊ n p 2 ⌋ + . . . x=\lfloor \frac{n}{p} \rfloor + \lfloor \frac{n}{p^2} \rfloor+... x=pn+p2n+...

  • 递推式为: f ( n ) = f ( ⌊ n p ⌋ ) + ⌊ n p ⌋ f(n)=f(\lfloor \frac{n}{p} \rfloor)+\lfloor \frac{n}{p} \rfloor f(n)=f(pn)+pn

LL qpow(LL a, LL n, LL m)//快速幂
{
    LL ans = 1;
    a %= m;
    while(n)
    {
        if(n & 1)
            ans = ans * a % m;
        n >>= 1;
        a = a * a % m;
    }
    return ans;
}

//求解ax+by=gcd(a, b)
//返回值为gcd(a, b)
LL exgcd(LL a, LL b, LL& x, LL& y)//扩展欧几里得
{
    LL d = a;
    if(b)
    {
        d = exgcd(b, a % b, y, x);
        y -= (a / b) * x;
    }
    else x = 1, y = 0;
    return d;
}

//求解a关于模上m的逆元
//返回-1表示逆元不存在
LL inv(LL a, LL m)
{
    LL x, y;
    LL d = exgcd(a, m, x, y);
    return d == 1 ? (m + x % m) % m : -1;
}

//计算n! mod p^k的部分值,pk为p_i的k_i次方,算出的答案不包括pi的幂的那一部分
LL Mul(LL n, LL pi, LL pk)
{
    if(!n) return 1;
    LL ans = 1;
    if(n / pk)
    {
        for(LL i = 2; i <= pk; i++) //求出循环节乘积
            if(i % pi) ans = ans * i % pk;
        ans = qpow(ans, n / pk, pk); //循环节次数为n / pk
    }
    for(LL i = 2; i <= n % pk; i++)
        if(i % pi) ans = ans * i % pk;
    return ans * Mul(n / pi, pi, pk) % pk;//递归求解
}

LL C(LL n, LL m, LL p, LL pi, LL pk)//计算组合数C(n, m) mod p^k的值 p^k为p_i的k-i次方
{
    if(m > n) return 0;
    LL a = Mul(n, pi, pk), b = Mul(m, pi, pk), c = Mul(n - m, pi, pk);
    LL k = 0, ans;//k为pi的幂值
    for(LL i = n; i; i /= pi) k += i / pi;
    for(LL i = m; i; i /= pi) k -= i / pi;
    for(LL i = n - m; i; i /= pi) k -= i / pi;
    ans = a * inv(b, pk) % pk * inv(c, pk) % pk * qpow(pi, k, pk) % pk;//ans就是n! mod pk的值
    ans = ans * (p / pk) % p * inv(p / pk, pk) % p;//此时用剩余定理合并解
    return ans;
}

LL Lucas(LL n, LL m, LL p)//求组合数C(n, m) mod p的值,p为合数
{
    LL x = p;
    LL ans = 0;
    for(LL i = 2; i <= p; i++)
    {
        if(x % i == 0)
        {
            LL pk = 1;
            while(x % i == 0)pk *= i, x /= i;//将p分解成质数幂的乘积
            ans = (ans + C(n, m, p, i, pk)) % p;//剩余定理求解
        }
    }
    return ans;
}

1.2 扩展欧几里得

a ∗ x + b ∗ y = g c d ( a , b ) a*x+b*y=gcd(a, b) ax+by=gcd(a,b)的解

//求解ax+by=gcd(a, b)
//返回值为gcd(a, b)
LL exgcd(LL a, LL b, LL& x, LL& y)
{
    LL d = a;
    if(b)
    {
        d = exgcd(b, a % b, y, x);
        y -= (a / b) * x;
    }
    else x = 1, y = 0;
    return d;
}

1.3 威尔逊定理

p可以整除(p-1)!+1是p为质数的充要条件

1.4 欧拉定理(扩展欧拉定理)【高次幂:对指数取模(模无限制)】

  • 欧拉定理:

​ 若a,m为整数,且a,m互质,则 a ϕ ( m ) ≡ 1   ( m o d   m ) a^{\phi(m)} \equiv 1\ (mod\ m) aϕ(m)1 (mod m)

  • 扩展欧拉定理:

a c ≡ { a c   m o d   ϕ ( m ) , g c d ( a , m ) = 1 a c , g c d ( a , m ) ≠ 1 , c < ϕ ( m ) a ( c   m o d   ϕ ( m ) ) + ϕ ( m ) , g c d ( a , m ) ≠ 1 , c ≥ ϕ ( m ) a^c \equiv\begin{cases}a^{c \ mod \ \phi(m)}, & gcd(a, m)=1\\ a^c, & gcd(a, m) \neq 1,c < \phi(m) \\a^{(c \ mod \ \phi(m))+\phi(m)}, & gcd(a, m) \neq 1,c \geq \phi(m) \end{cases} acac mod ϕ(m),ac,a(c mod ϕ(m))+ϕ(m),gcd(a,m)=1gcd(a,m)̸=1,c<ϕ(m)gcd(a,m)̸=1,cϕ(m)

  • 因此求高次幂,无论a,n是否互质,都可以使用 a c ≡ a ( c   m o d   ϕ ( m ) ) + ϕ ( m )   m o d   m a^c \equiv a^{(c \ mod \ \phi(m))+\phi(m)} \ mod \ m aca(c mod ϕ(m))+ϕ(m) mod m

1.5 费马小定理【高次幂:对指数取模(模为质数)】

​ m为质数

  • a不为m的倍数时, a ( m − 1 ) ≡ 1   ( m o d   m ) a^{(m-1)} \equiv 1 \ (mod \ m) a(m1)1 (mod m)
  • a为m的倍数时, a ( m − 1 ) ≡ 0   ( m o d   m ) a^{(m-1)} \equiv 0 \ (mod \ m) a(m1)0 (mod m)
  • 因此求高次幂,可以用该定理对指数取模

1.6 中国剩余定理

求线性同余方程组

{ X ≡ d 1   m o d   p 1 X ≡ d 2   m o d   p 2 . . . . . . X ≡ d n   m o d   p n \begin{cases} X \equiv d_1 \ mod \ p_1 \\ X \equiv d_2 \ mod \ p_2 \\...... \\X \equiv d_n \ mod \ p_n \end{cases} Xd1 mod p1Xd2 mod p2......Xdn mod pn

求X的值

const int N = 15;
int n;
LL yu[N], mo[N];

LL exgcd(LL a, LL b, LL &x, LL &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    LL r = exgcd(b, a % b, x, y);
    LL tmp = y;
    y = x - (a / b) * y;
    x = tmp;
    return r;
}

LL CRT(LL *yu, LL *mo, int num)
{
    LL M = 1, ans = 0, x, y;
    for(int i = 0; i < num; i++)
        M *= mo[i];
    for(int i = 0; i < num; i++)
    {
        LL w = M / mo[i];
        exgcd(w, mo[i], x, y);
        ans = (ans + yu[i] * x * w) % M;
    }
    return (ans + M) % M;
}

你可能感兴趣的:(模板,数论,-,欧拉函数,欧拉降幂,快速幂)