Алгоритм для определения неотрицательных значений существует существование для линейного диофантового уравнения

StackOverflow https://stackoverflow.com/questions/1467907

  •  13-09-2019
  •  | 
  •  

Вопрос

Я ищу метод, чтобы определить, есть ли решение таких уравнений, как:3n1+4n2+5n3 = 456, куда N1, N2, N3 положительные целые числа.

Или более общего: есть ли ноль или положительный целые числа N1, N2, N3... это решает уравнение k1n1+k2n2+k3n3 ... = m куда K1, K2, K3... а также м известны положительные целые числа.

Мне не нужно найти решение - просто чтобы определить, существует ли решение.

Редактировать:

Что касается практического использования этого алгоритма:

В библиотеке связи я хочу решить, является ли данное сообщение действительным в соответствии с ее размером, прежде чем обрабатывать сообщение. Например: я знаю, что сообщение содержит элементы с 3-байтами с нулевым или более 3-байтом, элементы 4-байтов нулевых или более нулевых или 5-байт-элементы. Я получил сообщение от 456 байтов, и я хочу определить ее достоверность, прежде чем еще больше осмотреть его содержание. Конечно, заголовок сообщения содержит количество элементов каждого типа, но я хочу внести первый инъекция на уровне коммуникационной библиотеки, пропустив что-то вроде pair<MsgType,vector<3,4,5>>.

Это было полезно?

Решение

Вы спрашиваете, есть ли регулярное выражение

(xxx | xxxx | xxxxx)*

Соответствует XX ... x, где X происходит 456 раз.

Вот решение в O (n+a^2), где A является наименьшим из чисел с левой стороны (в данном случае 3).

Предположим, ваши числа 6,7,15. Я позвоню по номеру, выражаемому в форме 6x+7y+15z «доступен». Вы должны проверить, доступен ли заданный номер.

Если вы можете получить какое -то число N, то, конечно, вы сможете получить n+6, n+12, n+18 - в целом, n+6k для всех k> = 0. с другой стороны, если Вы не можете получить какое-то число N, тогда N-6, безусловно, тоже недоступен (если бы вы могли получить (N-6), то (N-6)+6 = N будет доступен), это означает N-12, n-18, n-6k не доступны ни один.

Предположим, вы определили, что 15 доступно, но 9 нет. В нашем случае 15 = 6*0+7*0+15*1, но не сможет получить 9 каким -либо образом. Таким образом, по нашей предыдущей аргументировании, 15+6K доступно для всех k> = 0 и 9-6K для всех k> = 0 нет. Если у вас есть какое -то число, которое разделено на 6 дает 3 в качестве оставшегося (3, 9, 15, 21, ...), вы можете быстро ответить: числа <= 9 недоступны, числа> = 15 - это.

Достаточно определить для всех возможных остатков деления на 6 (то есть 0,1,2,3,4,5,5), какое наименьшее количество доступно. (Я только что показал, что это число для оставшихся 3).

Как это сделать: Создайте график с вершинами 0,1,2,3,4,5. Для всех чисел k, которые вам даны (7,15 - мы игнорируем 6) Добавить преимущество от x до (x + k) mod 6. Придайте ему вес (x + k) div 6. Использование Алгоритм Дейкстры используя 0 в качестве начального узла. Расстояния, найденные алгоритмом, будут именно теми числами, которые мы ищем.

В нашем случае (6,7,15) число 7 приводит к 0 -> 1 (вес 1), 1 -> 2 (вес 1), 2 -> 3 (вес 1), ..., 5 -> 0 (вес 1) и номер 15 дает 0 -> 3 (вес 2), 1 -> 4 (вес 2), ..., 5 -> 1 (вес 2). Самый короткий путь от 0 до 3 имеет один край - его вес 2. Таким образом, 6*2 + 3 = 15 - наименьшее число, которое дает 3 в качестве оставшегося. 6*1 + 3 = 9 недоступно (ну, мы проверили это ранее вручную).

А что такое связь с регулярными выражениями? Ну, каждое регулярное выражение имеет эквивалентный конечный автомат, и я построил один из них.

Эта проблема с разрешением нескольких запросов появилась на Польская олимпиада И я перевел решение. Теперь, если вы услышите, как человек, говорящий о том, что информатика не полезна для реальных программистов, ударите его по лицу.

Другие советы

Согласно с это, если наибольшим общим фактором {n1, n2, n3, ...} не является делителем М, тогда у вас нет решения. На этой странице показан пример только {n1, n2}, но она распространяется на более крупные системы. Новая проблема заключается в написании алгоритма для поиска наибольшего общего фактора, но это тривиально в свете первоначальной проблемы.

Таким образом, часть вашего алгоритма найдет GCF ({n1, n2, ...}), тогда посмотрите, является ли это фактором M. Если это не так, то нет решения не существует. Это не вполне показывает, что решение существует, но он может быстро показать вам, что ни один из них не существует, что все еще полезно.

Похоже, вы говорите о системе неравенства с целочисленными ограничениями. Реальность такова, что вы решаете эту систему:

k1n1+k2n2+k3n3...=m
n1 >= 0
n2 >= 0
n3 >= 0

И дополнительное ограничение, что N1, N2, N3 являются целыми числами. Это линейное программирование проблема. К сожалению для вас, общий случай решения такой системы с целочисленные ограничения являются NP-полными. Анкет Тем не менее, есть много алгоритмов, которые решат его для вас.

Это связано с Проблема с монетой Frobenius, который не был решен для n> 3.

Подход грубой силы (псевдокод):

def a = 3
def b = 4
def c = 5
def x = 456

for n1 = a to int(x / a) + 1 step a
  for n2 =b to int(x / b) + 1 step b
    for n3 = c to int(x / c) + 1 step c
      if a * n1 + b * n2 + c * n3 = x then
        print n1, n2, n3

Смотрите также http://mail.python.org/pipermail/python-list/2000-april/031714.html

РЕДАКТИРОВАТЬ: В библиотеке связи это не имеет смысла, поскольку она должна работать немедленно. В приложении ОП я, вероятно, использовал бы какой -то хэш, но его подход звучит интересно.

Вот что -то на 2 -й случае. Я еще не понял, как это масштабировать:

Учитывая 2 относительно основных целых чисел X и Y, существуют положительные целые числа A и B, так что ax+by=c для всех c>=(x-1)(y-1)

В основном это работает, потому что, если вы предполагаете x<y, вы можете выразить все целые числа мод x с (0, Y, 2y, 3y, ..., (x-1) y). Теперь, добавив некоторые положительные кратные x, вы можете достичь всех целых чисел между [(x-1) (y-1), (x-1) y], как все целые числа между (x-1) (y- 1) и (x-1) y-1 был выражен ранее.

  1. GCD (x, y). Если C не является множественным, верните false.
  2. Если gcd (x, y)> 1, разделите x, y, c by gcd
  3. Если C> (x-1) (y-1), верните True
  4. Иначе грубая сила

И для грубой силы:

if int(c/y) >= c*y^(-1) mod x, return true, 
else return false

Возможно, следующая информация не имеет значения, потому что она не справляется с общей ситуацией, но ...

Если проблема состоит в том, чтобы определить, может ли данное положительное целое число k сформировать как сумма 3*n1 + 4*n2 + 5*n3, для неотрицательных целых чисел n1, n2, n3, тогда ответ «да», для k> = 3.

Известный учебник Розена Дискретная математика и ее приложения, п. 287 из шестого издания, доказывает, что «каждое количество почтовых расходов в размере 12 центов или более может быть сформировано с использованием только 4 цента и 5 центов», используя индукцию.

Основным шагом является то, что почтовые расходы в размере 12 центов могут быть сформированы с 3 марками четырех центов.

На шаге индукции рассматривается, что если p (k) верно с использованием четырех ценных марков, то просто замените марку с четырьмя центами на штамп с пятью центами, чтобы показать, что p (k+1) является правдой. Если p (k) верно, не используя марки с четырьмя центами, то, поскольку K> = 12, нам нужно не менее 3 пять центов марок, чтобы сформировать нашу сумму, и 3 пять центов могут быть заменены на 4 четыре цента Марки для достижения K+1.

Чтобы расширить вышеуказанное решение для этой проблемы, требуется только рассмотрение всего еще нескольких случаев.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top