zoukankan      html  css  js  c++  java
  • 欧几里得和拓展欧几里得模板

    参考:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

     1 /*
     2 gcd求最大公约数,两数相乘在除gcd可以求最小公倍数
     3 */
     4 int gcd(int a, int b)
     5 {
     6     return b ? gcd(b, a % b) : a;
     7 }
     8 
     9 /*
    10 exgcd
    11 
    12 学习网址:http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html
    13 
    14 扩展欧几里德算法的应用主要有以下三方面:
    15 (1)求解不定方程; 找出一对整数(x, y), 使得 a*x + b*y = gcd(a, b).
    16 (2)求解模线性方程(线性同余方程);
    17 (3)求解模的逆元;
    18 
    19 结论1:若方程 ax + by = c 的一组整数解为(x0, y0),
    20 则它的任意整数解都可以写成(x0 + k * b', y0 + k * a'),其中 a' = a / gcd(a, b), b' = b / gcd(a, b), k 为任意整数.
    21 
    22 结论2:设a, b, c为任意整数, g = gcd(a, b), 方程 a*x + b*y = g 的一组解是(x0, y0), 则当 c 是 g 的倍数时
    23 a*x + b*y = c 的一组解是(x0*c/g, y0*c/g);当 c 不是 g 的倍数时无整数解.
    24 */
    25 int exgcd(int a, int b, int &x, int &y)
    26 {
    27     if(b == 0) {
    28         x = 1;
    29         y = 0;
    30         return a;
    31     }
    32     int r = exgcd(b, a % b, x, y);
    33     int t = x;
    34     x = y;
    35     y = t - a / b * y;
    36     return r;
    37 }
    38 
    39 /*
    40 (1) : 解不定方程 a * x + b * y = c
    41 */
    42 bool linear_equation(int a, int b, int c, int &x, int &y)
    43 {
    44     int d = exgcd(a, b, x, y);
    45     if(c % d) { //没有整数解
    46         return false;
    47     }
    48     int k = c / d;
    49     x = x * k, y = y * k; //求得的是其中一组解
    50     return true;
    51 }
    52 
    53 /*
    54 (2) : 求解模线性方程的解集 : a * x ≡ b (mod n)
    55       可以写成:a * x + n * y = b
    56 */
    57 bool modular_linear_equation(int a,int b,int n)
    58 {
    59     int x, y, x0, div;
    60     int d = exgcd(a, n, x, y); //解集共有d个数
    61     if(b % d) {
    62         return false;
    63     }
    64     x0 = x * (b / d) % n; //最小整数解
    65     div = n / d;
    66     if(div < 0) div = -div;
    67     //每一个解的间隔是 n/d ,共有 d 个解
    68     //如果有负数要变成正数
    69     /*
    70     求最小整数解: ans = x0 % div;
    71                  if(ans <= 0) ans += div;
    72            
    73            就是: ans = (x0 % div + div) % div;
    74                  return ans;
    75     */
    76     for(int i = 1; i <= d; i++) {
    77         printf("%d
    ", (x0 + i * div) % n);
    78     }
    79     return true;
    80 }
    81 
    82 /*
    83 (3) : 求解模的逆元:形如 a * x ≡ b (mod n) 的方程,如果gcd(a, n) == 1, 则方程只有唯一解
    84 在这种情况下,如果b == 1,同余方程就是 a * x ≡ 1 (mod n), gcd(a, n) = 1
    85 这时求出的 x 为 a 的对模 n 乘法的逆元
    86 用拓展欧几里得可以求出 x
    87 */
  • 相关阅读:
    position : sticky
    学习笔记之段落里面最后出现省略号
    two or more web modules defined in the configuration have the same context root
    Android笔记:ActivitySpinner
    设计一个通讯录的XML文件
    使用JDBC连接SQL Server数据库
    SNMP使用UDP传送报文。为什么不使用TCP?
    计算Java程序运行时间
    android在xml的textStyle中,设置一个字体是粗体或斜体或带有下划线
    schema.xml文件里datatype的定义格式
  • 原文地址:https://www.cnblogs.com/fightfordream/p/5767436.html
Copyright © 2011-2022 走看看