Формула для сравнений


10

Китайская теорема об остатках может быть весьма полезным в модульной арифметике.

Например, рассмотрим следующий набор конгруэнтных отношений:

Набор конгруэнтности

Для множеств конгруэнции отношений , как это, где все основания ( 3, 5, 7в данном примере) являются совместно простым друг с другом, там будет одно и только одно целым числом nмежду 1и продукт оснований ( 3*5*7 = 105в этом примере) включительно , которая удовлетворяет соотношения ,

В этом примере число будет 14сгенерировано по следующей формуле:

формула

где 2, 4, and 0приведены из приведенного выше примера.

70, 21, 15являются коэффициенты формулы и они зависят от оснований, 3, 5, 7.

Для вычисления коэффициентов формулы ( 70, 21, 15в нашем примере) для набора базисов мы используем следующую процедуру.

Для каждого номера aв наборе основ:

  1. Найдите произведение всех других основ, обозначенных как P.
  2. Найдите первое кратное, Pкоторое оставляет остаток от 1деления на a. Это коэффициент a.

Например, чтобы вычислить коэффициент, который соответствует основанию 3, мы находим произведение всех других оснований (то есть 5*7 = 35), а затем находим первое кратное этого произведения, которое оставляет остаток от 1деления на основание.

В этом случае 35оставляет остаток от 2деления на 3, но 35*2 = 70оставляет остаток от 1деления на 3, 70как и соответствующий коэффициент для 3. Точно так же 3*7 = 21оставляет остаток от 1деления на 5и 3*5 = 15оставляет остаток от 1деления на 7.

В двух словах

Для каждого номера aв наборе номеров:

  1. Найдите произведение всех других чисел, обозначенных как P.
  2. Найдите первое кратное, Pкоторое оставляет остаток от 1деления на a. Это коэффициент a.

Соревнование

  • Задача состоит в том, чтобы для набора из двух или более баз найти набор соответствующих коэффициентов.
  • Множество оснований, как гарантируют, будут попарно взаимно простыми, и каждое основание, как гарантируют, будет больше чем 1.
  • Ваши входные данные представляют собой список целых чисел в виде [3,4,5]строки ввода или строки, разделенных пробелами, "3 4 5"или же ваши входные данные работают.
  • Ваш вывод должен быть либо списком целых чисел, либо строкой через пробел, которая обозначает набор коэффициентов.

Контрольные примеры

input             output
[3,5,7]           [70,21,15]
[2,3,5]           [15,10,6]
[3,4,5]           [40,45,36]
[3,4]             [4,9]
[2,3,5,7]         [105,70,126,120]
[40,27,11]        [9801,7480,6480]
[100,27,31]       [61101,49600,56700]
[16,27,25,49,11]  [363825,2371600,2794176,5583600,529200]

Большое спасибо Leaky Nun за помощь в написании этой задачи. Как всегда, если проблема неясна, пожалуйста, дайте мне знать. Удачи и хорошего гольфа!


Всегда ли будет 3 цифры на входе?
xnor

@xnor Нет. Тестовые случаи отредактированы.
Sherlock9

Ответы:


5

Haskell, 61 55 53 байта

f x=[[p|p<-[0,product x`div`n..],p`mod`n==1]!!0|n<-x]

Определяет функцию, fкоторая принимает входные данные и выдает выходные данные в виде списка целых чисел.

f x=[                                          |n<-x]  (1)
              product x                                (2)
                       `div`n                          (3)

Сначала мы перебираем все целые числа на входе (1). Затем мы берем произведение всех целых чисел (2) и делим на n, чтобы получить просто произведение нецелых nчисел, которое равно P(3).

           [0,               ..]                       (4)
     [p|p<-                     ,p`mod`n==1]           (5)
                                            !!0        (6)

Затем мы используем result ( P) в качестве значения шага для диапазона, начинающегося с нуля (4). Мы берем результат [0, P, 2P, 3P, ...]и фильтруем его по значениям, для которых результат операции mod-n равен единице (5). Наконец, мы берем первый элемент, который работает благодаря ленивой оценке (6).

Спасибо @xnor за 2 байта!


1
Добро пожаловать в Haskell! Я думаю, что вы quotможете быть div, и headможет быть !!0.
xnor

4

Желе , 11 7 байт

P:*ÆṪ%P

Попробуйте онлайн! или проверьте все контрольные примеры .

Фон

Пусть P и a строго положительные, взаимно простые числа.

Двухэтапный процесс в вопросе - поиск кратного P, который оставляет остаток от 1 при делении на a - может быть описан следующим уравнением сравнения.

линейное уравнение конгруэнции

По теореме Эйлера-Ферма имеем

Теорема Эйлера-Ферма

где φ обозначает функцию Эйлера . Из этого результата мы выводим следующее.

формула для линейного уравнения конгруэнции

Наконец, поскольку задача требует от нас вычисления Px , мы наблюдаем, что

формула для конечного результата

где Pa можно рассчитать как произведение всех модулей.

Как это работает

P:*ÆṪ%P  Main link. Argument: A (list of moduli)

P        Yield the product of all moduli.
 :       Divide the product by each modulus in A.
   ÆṪ    Apply Euler's totient function to each modulus.
  *      Raise each quotient to the totient of its denominator.
     %P  Compute the remainder of the powers and the product of all moduli.

2

J 13 байт

*/|5&p:^~*/%]

На основании удивительного ответа @Dennis .

Применение

Некоторые тестовые случаи потребуют ввода в виде расширенных целых чисел с суффиксом x.

   f =: */|5&p:^~*/%]
   f 3 5 7
70 21 15
   f 40x 27 11
9801 7480 6480
   f 16x 27 25 49 11
363825 2371600 2794176 5583600 529200

объяснение

*/|5&p:^~*/%]  Input: list B
         */    Reduce B using multiplication to get the product of the values
            ]  Identity function, get B
           %   Divide the product by each value in B, call the result M
   5&p:        Apply the totient function to each value in B, call the result P
       ^~      Raise each value in M to the power of its corresponding value in P
*/             The product of the values in B
  |            Compute each power modulo the product and return

Попробуй это здесь.




1

Желе, 14 13 байт

P:×"Ḷð%"’¬æ.ḷ

Сохраненный байт благодаря @ Деннис !

Использует процесс, описанный в спецификации задачи. Входные данные представляют собой список базисов, а выходные данные представляют собой список коэффициентов.

Попробуйте онлайн или проверьте все контрольные примеры .

объяснение

P:×"Ḷð%"’¬æ.ḷ  Input: a list B
P              Get the product of the list
 :             Divide it by each value in the B, call it M
    Ḷ          Get a range from 0 to k for k in B
  ×"           Vectorized multiply, find the multiples of each M
     ð         Start a new dyadic chain. Input: multiples of M and B
      %"       Vectorized modulo, find the remainders of each multiple by B
        ’      Decrement every value
               If the remainder was 1, decrementing would make it 0
         ¬     Logical NOT, zeros become one and everything else becomes 0
            ḷ  Get the multiples of M
          æ.   Find the dot product between the modified remainders and the multiples
               Return

1

JavaScript (ES6), 80 байт

a.map(e=>[...Array(e).keys()].find(i=>p*i/e%e==1)*p/e,p=a.reduce((i,j)=>i*j))

Я пробовал расширенный евклидов алгоритм, но он занимает 98 байт:

a=>a.map(e=>(r(e,p/e)+e)%e*p/e,p=a.reduce((i,j)=>i*j),r=(a,b,o=0,l=1)=>b?r(b,a%b,t,o-l*(a/b|0)):o)

Если все значения простые, ES7 может сделать это в 56 байтах:

a=>a.map(e=>(p/e%e)**(e-2)%e*p/e,p=a.reduce((i,j)=>i*j))

1

Python + SymPy, 71 байт

from sympy import*
lambda x:[(prod(x)/n)**totient(n)%prod(x)for n in x]

Это использует алгоритм из моего ответа желе . Ввод / вывод осуществляется в виде списков номеров SymPy.


1

Python 2, 87 84 байта

Простая реализация алгоритма. Предложения по игре в гольф приветствуются.

a=input();p=1
for i in a:p*=i
print[p/i*j for i in a for j in range(i)if p/i*j%i==1]

Полная программа сэкономит 3 байта.
Деннис


0

GAP , 51 байт

В GAP есть функция, с помощью которой можно вычислить мотивирующий пример ChineseRem([2,5,7],[2,4,0]), но это все же не позволяет легко получить коэффициенты. Мы можем получить n-й коэффициент, используя список с единицей в n-й позиции и нулями в других позициях в качестве второго аргумента. Поэтому нам нужно создать эти списки и применить функцию ко всем из них:

l->List(Basis(Integers^Size(l)),b->ChineseRem(l,b))

0

Пакетный, 148 байт

@set p=%*
@set/ap=%p: =*%
@for %%e in (%*)do @for /l %%i in (1,1,%%e)do @call:l %%e %%i
@exit/b
:l
@set/an=p/%1*%2,r=n%%%1
@if %r%==1 echo %n%

0

На самом деле, 14 байтов

Это использует алгоритм в ответе желе Денниса . Еще один ответ, основанный на моем ответе на Python, готовится к публикации. Предложения по игре в гольф приветствуются. Попробуйте онлайн!

;π;)♀\;♂▒@♀ⁿ♀%

Как это работает

                 Implicit input a.
;                Duplicate a.
 π;)             Take product() of a, duplicate and rotate to bottom.
    ♀\           Integer divide the product by each element of a. Call this list b.
      ;♂▒        Take that list, duplicate, and get the totient of each element.
         @♀ⁿ     Swap and take pow(<item in b>, <corresponding totient>)
            ♀%   Modulo each item by the remaining duplicate product on the stack.
                 Implicit return.

Еще один ответ, основанный на моем ответе на Python в 22 байта. Предложения по игре в гольф приветствуются. Попробуйте онлайн!

;π╖`╝╛╜\╛r*"╛@%1="£░`M

Как это работает

            Implicit input a.
;π╖         Duplicate, take product of a, and save to register 0.
`...`M      Map over a.
  ╝           Save the item, b, in register 1.
  ╛╜\         product(a) // b. Call it P.
  ╛r          Take the range [0...b].
  *           Multiply even item in the range by P. Call this list x.
  "..."£░     Turn a string into a function f.
              Push values of [b] where f returns a truthy value.
    ╛@%         Push b, swap, and push <item in x> % b.
    1=          Does <item> % b == 1?
            Implicit return.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.