Matrix_code

math - Euclid

Feb 11th, 2017 (edited)
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.08 KB | None | 0 0
  1. // This is a collection of useful code for solving problems that
  2. // involve modular linear equations.  Note that all of the
  3. // algorithms described here work on nonnegative integers.
  4.  
  5. #include <iostream>
  6. #include <vector>
  7. #include <algorithm>
  8.  
  9. using namespace std;
  10.  
  11. typedef vector<long long> VI;
  12. typedef pair<long long, long long> PII;
  13.  
  14. // return a % b (positive value)
  15. long long mod(long long a, long long b) {
  16.     return ((a%b) + b) % b;
  17. }
  18.  
  19. // computes gcd(a,b)
  20. long long gcd(long long a, long long b) {
  21.     while (b) { long long t = a%b; a = b; b = t; }
  22.     return a;
  23. }
  24.  
  25. // computes lcm(a,b)
  26. long long lcm(long long a, long long b) {
  27.     return a / gcd(a, b)*b;
  28. }
  29.  
  30. // (a^b) mod m via successive squaring
  31. long long powermod(long long a, long long b, long long m)
  32. {
  33.     long long ret = 1;
  34.     while (b)
  35.     {
  36.         if (b & 1) ret = mod(ret*a, m);
  37.         a = mod(a*a, m);
  38.         b >>= 1;
  39.     }
  40.     return ret;
  41. }
  42.  
  43. // returns g = gcd(a, b); finds x, y such that d = ax + by
  44. long long extended_euclid(long long a, long long b, long long &x, long long &y) {
  45.     long long xx = y = 0;
  46.     long long yy = x = 1;
  47.     while (b) {
  48.         long long q = a / b;
  49.         long long t = b; b = a%b; a = t;
  50.         t = xx; xx = x - q*xx; x = t;
  51.         t = yy; yy = y - q*yy; y = t;
  52.     }
  53.     return a;
  54. }
  55.  
  56. // finds all solutions to ax = b (mod n)
  57. VI modular_linear_equation_solver(long long a, long long b, long long n) {
  58.     long long x, y;
  59.     VI ret;
  60.     long long g = extended_euclid(a, n, x, y);
  61.     if (!(b%g)) {
  62.         x = mod(x*(b / g), n);
  63.         for (long long i = 0; i < g; i++)
  64.             ret.push_back(mod(x + i*(n / g), n));
  65.     }
  66.     return ret;
  67. }
  68.  
  69. // computes b such that ab = 1 (mod n), returns -1 on failure
  70. long long mod_inverse(long long a, long long n) {
  71.     long long x, y;
  72.     long long g = extended_euclid(a, n, x, y);
  73.     if (g > 1) return -1;
  74.     return mod(x, n);
  75. }
  76.  
  77. // Chinese remainder theorem (special case): find z such that
  78. // z % m1 = r1, z % m2 = r2.  Here, z is unique modulo M = lcm(m1, m2).
  79. // Return (z, M).  On failure, M = -1.
  80. PII chinese_remainder_theorem(long long m1, long long r1, long long m2, long long r2) {
  81.     long long s, t;
  82.     long long g = extended_euclid(m1, m2, s, t);
  83.     if (r1%g != r2%g) return make_pair(0, -1);
  84.     return make_pair(mod(s*r2*m1 + t*r1*m2, m1*m2) / g, m1*m2 / g);
  85. }
  86.  
  87. // Chinese remainder theorem: find z such that
  88. // z % m[i] = r[i] for all i.  Note that the solution is
  89. // unique modulo M = lcm_i (m[i]).  Return (z, M). On
  90. // failure, M = -1. Note that we do not require the a[i]'s
  91. // to be relatively prime.
  92. PII chinese_remainder_theorem(const VI &m, const VI &r) {
  93.     PII ret = make_pair(r[0], m[0]);
  94.     for (long long i = 1; i < m.size(); i++) {
  95.         ret = chinese_remainder_theorem(ret.second, ret.first, m[i], r[i]);
  96.         if (ret.second == -1) break;
  97.     }
  98.     return ret;
  99. }
  100.  
  101. // computes x and y such that ax + by = c
  102. // returns whether the solution exists
  103. bool linear_diophantine(long long a, long long b, long long c, long long &x, long long &y) {
  104.     if (!a && !b)
  105.     {
  106.         if (c) return false;
  107.         x = 0; y = 0;
  108.         return true;
  109.     }
  110.     if (!a)
  111.     {
  112.         if (c % b) return false;
  113.         x = 0; y = c / b;
  114.         return true;
  115.     }
  116.     if (!b)
  117.     {
  118.         if (c % a) return false;
  119.         x = c / a; y = 0;
  120.         return true;
  121.     }
  122.     long long g = gcd(a, b);
  123.     if (c % g) return false;
  124.     x = c / g * mod_inverse(a / g, b / g);
  125.     y = (c - a*x) / b;
  126.     return true;
  127. }
  128.  
  129. int main() {
  130.     // expected: 2
  131.     cout << gcd(14, 30) << endl;
  132.  
  133.     // expected: 2 -2 1
  134.     long long x, y;
  135.     long long g = extended_euclid(14, 30, x, y);
  136.     cout << g << " " << x << " " << y << endl;
  137.  
  138.     // expected: 95 451
  139.     VI sols = modular_linear_equation_solver(14, 30, 100);
  140.     for (int i = 0; i < sols.size(); i++) cout << sols[i] << " ";
  141.     cout << endl;
  142.  
  143.     // expected: 8
  144.     cout << mod_inverse(8, 9) << endl;
  145.  
  146.     // expected: 23 105
  147.     //           11 12
  148.     PII ret = chinese_remainder_theorem(VI({ 3, 5, 7 }), VI({ 2, 3, 2 }));
  149.     cout << ret.first << " " << ret.second << endl;
  150.     ret = chinese_remainder_theorem(VI({ 4, 6 }), VI({ 3, 5 }));
  151.     cout << ret.first << " " << ret.second << endl;
  152.  
  153.     // expected: 5 -15
  154.     if (!linear_diophantine(7, 2, 5, x, y)) cout << "ERROR" << endl;
  155.     cout << x << " " << y << endl;
  156.     return 0;
  157. }
Add Comment
Please, Sign In to add comment