GCD && ExtendGCD

 

之前版本

 

 计算最大公约数和不定方程

•GCD相关性质

性质1.GCD(a,b) = GCD(-a,b) = GCD(a,-b) = GCD( |a| , |b| );

性质2.GCD(a,b) = GCD(a,a-b) = GCD(b,a-b);  

性质2推广.GCD(a,b,c) = GCD(a,b-a,c-b) => GCD(a1,a2,...,an) = GCD(a1,a2-a1,...,an-an-1);  

性质3.GCD(a,b) = GCD(a%b,a);

性质4.GCD(fib[a],fib[b]) = fib[ GCD(a,b) ];(fib[ i ] : 斐波那契数列的第 i 项)

性质5.GCD(a,b)·LCM(a,b) = a*b;

性质6.设 Gcd(m,a) = 1,则有 Gcd(m,ab) = Gcd(m,b);

     这就是说“求 m 与另一个数的最大公约数时,可以把另一个数中与 m 互素的因数去掉”

性质7.设 Gcd(m,a) = 1,那么若 m | ab,则 m | b;

     这就是说“若一个数被 m 整除,则把这个数中与 m 互素的因数去掉后仍被 m 整除”。

 

与GCD相关的习题

  [1]:Codeforces [2]:? [3]:POJ2773

•不定方程

  Bezout定理.如果 a,b 都是整数,则 ∃x,y 使得 ax+by = GCD(a,b);

  Bezout定理推广.如果 a,b 都是整数,且 GCD(a,b) | c,则 ∃x,y 使得 ax+by = c;

•利用拓展欧几里得算法求解不定方程

  

  由此可知,x1,y1 基于 x2,y2

  一直执行欧几里得算法来到最后一步GCD(0,ai) 的前一步 GCD(ai,bi);

  即 ai·xi+bi·yi = GCD(ai,bi) = ai;

  所以,此时,满足此式的一个解为 xi=1,yi=0;

  然后,根据上述推到的式子,向前回溯,依次求出 (xi-1,yi-1),(xi-2,yi-2),...,(x,y);

  如果式子来到 GCD(0,ai) 相当于求出 xi+1=0,yi+1=1;

  依次向前求出 (xi=1,yi=0),(xi-1,yi-1),(xi-2,yi-2),...,(x,y);

•extendGCD代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 /**
 5     拓展欧几里得求解 ax+by=GCD(a,b) 的一组解(x,y)
 6 */
 7 int extendGCD(int a,int b,int &x,int &y)
 8 {
 9     if(b%a == 0)
10     {
11         x=1,y=0;///ax+by=a其中的一组解
12         return a;
13     }
14 
15 //    int gcd=extendGCD(b%a,a,x,y);
16 //    int x2=x;
17 //    int y2=y;
18 //    y=x2;
19 //    x=y2-b/a*x2;
20 
21 //    15~19可化简为22~23
22     int gcd=extendGCD(b%a,a,y,x);
23     x -= b/a*y;
24 
25     return gcd;
26 }
27 int main()
28 {
29     int a,b;
30     while(~scanf("%d%d",&a,&b))
31     {
32         int x,y;
33         int gcd=extendGCD(a,b,x,y);
34         printf("%d*%d+%d*%d=%d\n",a,x,b,y,gcd);
35     }
36 }
View Code

与extendGCD相关的习题

  [1]:Codeforces

转载于:https://www.cnblogs.com/violet-acmer/articles/11232879.html

import random def fastExpMod(a, e, m): a = a % m res = 1 while e != 0: if e&1: res = (res * a) % m e >>= 1 #右移一位 a = (a * a) % m return res # 求最大公约数 def gcd(a, b): if b == 0: return a else: return gcd(b, a % b) # 扩展欧几里德算法求逆元 def extend_gcd(a, b): if b == 0: return 1, 0 else: x, y = extend_gcd(b, a % b) x, y = y, x - (a // b) * y return x, y # ElGamal密钥生成 def generate_key(p, g, x): y = pow(g, x, p) return (p, g, y, x), (p, g, y) # ElGamal加密 def encrypt(p, g, y, m): #Bob -- 加密 r = fastExpMod(g, k, p) c = (m * fastExpMod(y, k, p)) % p return r, c # ElGamal解密 def decrypt(ciphertext, private_key): r, c = ciphertext _, _, y = private_key k_inverse = extend_gcd(pow(r, p - 1 - y, p), p)[0] msg = chr((k_inverse * c) % p) return msg # 用户输入素数p和生成元g p = int(input("请输入一个大素数p:")) g = int(input("请输入一个在模p下的生成元g:")) # 用户输入私钥x和明文m x = int(input("请输入一个小于p-1的私钥x:")) m = input("请输入需要加密的明文m:") k= int(input('请输入一个随机数k:')) y = fastExpMod(g, k, p) # 生成ElGamal公钥和私钥 public_key, private_key = generate_key(p, g, x) # 对消息进行加密 ciphertext = encrypt(p, g, y, m) # 对密文进行解密 decrypted_msg = decrypt(ciphertext, private_key) # 输出结果 print(f"原始消息: {m}") print(f"加密后的消息: {ciphertext}") print(f"解密后的消息: {decrypted_msg}",改代码有误问题
06-10
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值