数论基础(gcd + 拓展欧几里得)

求连个数的最大公约数gcd:

typedef long long ll;
const int MAXN = 10000 + 7;

ll gcd(ll a, ll b) {
        return b ? gcd(b, a%b) : a;
}

拓展欧几里得:

欧几里得定理:  gcd(a, b) = gcd(b, a%b);

gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)

扩展欧几里德算法是用来在已知a, b求解一组x,y使得ax+by = Gcd(a, b) =r(解一定存在,根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程

方程组中。

假设:

a*x0 + b*y0 = gcd(a, b) = r

b*x1 + (a%b)*y1 = gcd(b, a%b) = r

......(依次递推)

b`*x + (a%b`)*y = gcd = r

当a%b`=0亦即递归终止时,不妨令x = 1, y = 0;则可以据此依次网上递推求出x1, y1; x0, y0, 又a%b = a - (a/b)*b 整除;则有:

b*x1 + [a - (a/b)*b]*y1 = r;

a*y1 + b[x1 - (a/b)*y1] = r; 对比a*x0 + b*y0 = r 系数有:

x0=y1,y0=x1-(a/b)*y1;

typedef long long ll;
ll extend_Euclid(ll a, ll b, ll& x, ll&y) {
        if(b == 0) {
                x = 1;
                y = 0;
                return a;
        }
        ll ans = extend_Euclid(b, a%b, x, y);
        ll tmp = x;
        x = y;
        y = tmp - a/b*y;
        return ans;
}


求解线性方程:

bool linerEquation(ll a, ll b, ll c, ll& x, ll& y) {
        ll d = extend_Euclid(a, b, x, y);
        if(c % d) return false;
        x *= d, y *= d;
        return true;
}

利用拓展欧几里得求逆元:

首先模的运算性质:

模运算与基本四则运算有些相似,但是除法例外。其规则如下:
  1. (a + b) % p = (a % p + b % p) % p
  2. (a - b) % p = (a % p - b % p) % p
  3. (a * b) % p = (a % p * b % p) % p
  4. a ^ b % p = ((a % p)^b) % p
  • 结合律:
    ((a+b) % p + c) % p = (a + (b+c) % p) % p
    ((a*b) % p * c)% p = (a * (b*c) % p) % p
  • 交换律:
    (a + b) % p = (b+a) % p
    (a * b) % p = (b * a) % p
  • 分配律:
    (a+b) % p = ( a % p + b % p ) % p
    ((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p

重要定理

  • 若a≡b (% p),则对于任意的c,都有(a + c) ≡ (b + c) (%p);
  • 若a≡b (% p),则对于任意的c,都有(a * c) ≡ (b * c) (%p);
  • 若a≡b (% p),c≡d (% p),则 (a + c) ≡ (b + d) (%p),(a - c) ≡ (b - d) (%p),
    (a * c) ≡ (b * d) (%p),(a / c) ≡ (b / d) (%p); 
故当我们要求(x * 1/a) mod  m 时,由于除法没有模运算法则,故可用逆元将除法转化成乘法。
(x*1/a) % m = (x%m * (1/a)%m) % m

逆元:对于正整数,如果有ay≡ 1 (mod m),那么把这个同余方程中y的最小正整数解叫做的逆元。
对上式两边除a则有:y ≡ 1/a(mod m), 故
(x*1/a)%m=(x%m*(1/a)%m)%m=(x%m*y%m)%m
即求
a*x - m*k = 1的x的最小非负整数解(-m看做y)
用扩展欧几里得求逆元:

ll inverseEle(ll a, ll b) {    // a关于1模b的逆元
        ll x, y;
        extend_Euclid(a, b, x, y);
        x = (x%b + b) % b;
        return x;
}


用费马小定理求逆元:
当a, m互质时,有
a^m≡a(mod m)
亦即
a^(m-1)≡1/a(mod m)
a * a^(m-2)≡1(mod m)
// x关于1模m的逆元, x,m互质, x^(m-2) 则x的逆元为x^(m-2)
ll inverseElePlus(ll x, ll m) { 
        m -= 2;
        ll ans = 1;
        while(m) {
                if(m & 1) ans *= x;
                x *= x;
                m >>= 1;
        }
        return ans;
}


你可能感兴趣的:(Algorithms,Number,Theory,Mathematics)