разбить число на сумму произведений его составляющих

253
20 октября 2017, 16:23

Есть число, например 111, так же есть ещё 2 числа 3 и 5 на которые число 111 должно разделиться без всяких остатков и прочего... может быть не совсем правильно словами объясняю, вот пример как это должно выглядеть:

21*5+2*3 = 111

Я не могу сформулировать нормально для своего понимания как это должно выглядеть словами, не то чтобы написать конкретный алгоритм =) собственно кто может объяснить сам принцип? хотя бы математически как то это расписать....

Answer 1

Решение в целых числах диофантовых уравнений вида a⋅x + b⋅y = c можно свести к поиску коэффициентов Безу.

Если x, y решения уравнения a⋅x + b⋅y = d, где d = gcd(a, b), тогда решением исходного уравнения будет пара: с₁⋅x, с₁⋅y, где с₁ = c / d. Отсюда:

  • если c не делится на gcd(a, b), то целых решений нет
  • начальное решение можно найти используя расширенный алгоритм Евклида
  • имея начальное решение (x₀, y₀), можно найти бесконечное количество решений по формуле: (x₀ + k⋅u, y₀ - k⋅v), где k произвольное целое, а u, v:

    u = b / gcd(a, b)
    v = a / gcd(a, b)
    

gcd(a, b) это наибольший общий делитель. Если решение есть, то существуют такое решение x, y, что abs(x) < abs(u) и abs(y) < abs(v).

Используя код для нахождения коэффициентов Безу из вики:

/// find integer x,y such that a*x + b*y = gcd(a, b) 
function find_bezout_coeff(a, b) { 
  var p = 1, 
    q = 0, 
    r = 0, 
    s = 1, 
    x, y; 
 
  while (a != 0 && b != 0) { 
    if (a >= b) { 
      a = a - b; 
      p = p - r; 
      q = q - s; 
    } else { 
      b = b - a; 
      r = r - p; 
      s = s - q; 
    } 
  } 
  if (a != 0) { 
    x = p; 
    y = q; 
  } else { 
    x = r; 
    y = s; 
  } 
  return [x, y]; 
} 
 
/// find integer x,y such that a*x + b*y = c 
function solve_diophantine(a, b, c) { 
  var [x, y] = find_bezout_coeff(a, b), 
    d = a * x + b * y; // gcd(a, b); 
  if (c % d != 0) 
    return "no solution"; 
 
  // solution: (c*x+k*b)/d, (c*y-k*a)/d for any k in Z 
  var c1 = c / d; 
  return [c1 * x, c1 * y, d]; 
} 
 
(function() { 
  var a = 3, 
    b = 5, 
    c = 111; 
  var [x, y, d] = solve_diophantine(a, b, c); 
  console.log(`result: a*x+b*y=c: (${a}*${x} + ${b}*${y}) == ${a*x+b*y}`); 
  console.assert((a * x + b * y) == c); 
  for (var k = -3; k < 4; ++k) { 
    var xx = x + k * b / d, 
      yy = y - k * a / d; 
    console.log(`result: a*x+b*y=c: (${a}*${xx} + ${b}*${yy}) == ${a*xx+b*yy}`); 
    console.assert((a * xx + b * yy) == c); 
  } 
})();

Answer 2

То, что вы хотите решить, называется линейным диофантовым уравнением и:

  1. может быть неразрешимо (например, если вы хотите «разделить» 111 не на 5 и 3, а скажем, на 5 и 10).
  2. если разрешимо — имеет бесконечно много решений в целых числах.

Алгоритмически, пожалуй, проще всего действовать подбором, хотя с точки зрения эффективности это, пожалуй, не лучший способ:

ax + by = с

Выбрать большее (чтоб считать меньше :)), скажем, это a, и для x от 0 до c / a (деление целочисленное) вычислять c - ax и смотреть, делится ли оно на b.

READ ALSO
проблема с отправкой Emita с девайса в js код

проблема с отправкой Emita с девайса в js код

Доброго времени суток всем) стоит задача переписать существующий модуль к ios устройствам для react native, а если точнее добавить таймаут при передачи...

240
Добавить символ плюс в маску

Добавить символ плюс в маску

Составил регулярное выражение,но не соображу, как добавить символ плюса вначале

265
ASP.NET не отрабатывает javascript

ASP.NET не отрабатывает javascript

ЗдравствуйтеЕсть проект ASP

474
Как подключить модуль с GitHub в свой проект?

Как подключить модуль с GitHub в свой проект?

Часто встречаю на GitHub модули, в описании которых присутствуют примерно такие строки: old school Grab file from dist directory

342