Формула конгрегенцій


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]

Велика подяка Лікі монахині за допомогу в написанні цього виклику. Як завжди, якщо проблема неясна, будь ласка, повідомте мене про це. Успіхів і хорошого гольфу!


Чи завжди у введенні будуть 3 числа?
xnor

@xnor Nope. Тестові справи відредаговані.
Шерлок9

Відповіді:


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)

Тоді ми використовуємо результат ( 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 , ми це спостерігаємо

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

де Па можна обчислити як добуток усіх модулів.

Як це працює

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:×"Ḷð%"’¬æ.ḷ

Збережено байт завдяки @ Dennis !

Використовує процес, описаний у специфікації виклику. Вхід - це перелік баз, а вихід - список коефіцієнтів.

Спробуйте в Інтернеті або Перевірте всі тестові випадки .

Пояснення

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]

Для цього використовується алгоритм з моєї відповіді Jelly . Введення / виведення у формі списків номерів 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.