数论总结(不断更新中)

1.欧几里得算法

计算a, b的gcd(最大公约数),设k  = gcd(a, b),则a = pk, b = qk。这里假设a > b,那么a % b = c,c = a - tb,将a,b替换掉得到c = pk - tqk,这里可以看见k也是c的约数。那么通过这样不停得取余,最终会得到x % 0 ,这时最大公约数就是x

示例30和35

35 % 30 = 5

30 % 5 = 0

所以最大公约数是5

int gcd(int a, int b){
    return b == 0 ? a : gcd(b, a % b);//如果这里a < b的话经过一次递归会将a, b互换
}
复杂度是O(logN)


2.扩展欧几里得

如果gcd(a, b) = k,则一定存在x, y使得ax+by=k成立。特别的当a, b互质的时候ax+by=1(详见斐蜀定理)

这里扩展欧几里得是也要求出来x, y


ax' + by' = gcd(a, b)

bx + (a % b)y = gcd(a, b),这里因为gcd(a%b, b) = gcd(a, b)

那么a % b = a - a / b * b

带入得到ay + b(x - a / b * y) = gcd(a, b)

那么们已知x, y就可以求的x‘,y’了

x‘ = y

y’ = x - a / b * y

那么我们怎么能知道一对x和y呢,回想一下我们的终止条件,是不是余数等于0这时的b就是我们的gcd

实例66, 42

66 % 42 = 24

42 % 24 = 18

24 % 18 = 6这里的式子的答案是不是gcd(66,42),我们从这里可以轻易知道24

18 % 6 = 0

6 % 0这时式子终止

那么我们以a = 6, b = 0,得到6x - 0y = 6,所以这里我们赋值x = 1,y = 0

这样我们就可以不停向上计算了。

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

扩展欧几里得应用,主要是为了求逆元来求解同余方程,我们有同余方程ax ≡b(mod p),那么我们称A*A‘≡1(mod p),我们称A’为A在mod p下面的逆元,也可以写A^-1,不这样写主要是为了和1 / A分开。我们化简一下这个式子A*A‘ - t * p = 1,在这里是不是和我们的斐蜀定理的式子很像。当gcd(A, p) = 1的时候逆元是存在的,而当gcd(A, p) != 1的时候逆元是不存在的。

那么原式就等于a’ * a * x ≡ b * a‘(mod p),应为a’*a在mod p的时候为1,所以又等于x≡b * a‘(mod p)原式求解。


同余里面还有关于除法的定义,如果AC≡BC(MOD P),就可以化简为A≡B(MOD P / gcd(C, P)),这样又可以和费马小定理对应上。

所以在求解已知A = BT,A % P = C,求A / B % P的答案就相当于BT≡C(mod p), 得到B'BT≡CB'(MOD P),得到T≡CB'(mod p),所以A ≡ B(mod P),那么A / C % P 就等于B * C’(MOD P),前提是C必须在mod P下有逆元。

(这里写的有点乱,请见谅。。。。)


逆元的模板

int mod_inversion(int a, int p){
    int x, y;
    int d = extgcd(a, p, x, y);
    if(d == 1){
        return (x % m + m) % m;//x可能求出有负数的情况,这里转为正数
    }
    return -1;//没有逆元
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值