Обчисліть зворотну цілу модуль 100000000003


21

Завдання наступне. З огляду на ціле число x(таке, що xмодуль 100000000003не дорівнює 0), представлене у вашому коді будь-яким способом, який вам здається зручним, виведіть інше ціле число y < 100000000003так, щоб (x * y) mod 100000000003 = 1.

Код повинен зайняти менше 30 хвилин, щоб запустити на стандартній настільній машині будь-який вхід, xтакий |x| < 2^40.

Тестові кейси

Вхід: 400000001. Вихід: 65991902837

Вхід: 4000000001. Вихід: 68181818185

Вхід: 2. Вихід: 50000000002

Вхід: 50000000002. Вихід: 2.

Вхід: 1000000. Вихід: 33333300001

Обмеження

Ви не можете використовувати будь-які бібліотеки або вбудовані функції, які виконують арифметичну модуль (або цю зворотну операцію). Це означає, що ви навіть не можете обійтися, a % bне реалізуючи %себе. Однак ви можете використовувати всі інші вбудовані функції арифметики без модуля.

Подібне запитання

Це схоже на це питання, хоча, сподіваємось, досить різне, щоб все ж зацікавити.


Отже, a- (a / b) * b добре?
користувач253751

@immibis Це добре виглядає.

тег: обмежений код?
Феліпе Нарді Батіста

1
Що особливого 100000000003? (просто цікаво)
NoOneIsHere

1
@ Лембік У такому випадку ви могли б згадати ту вимогу, яку y <100000000003 у запитанні?
isaacg

Відповіді:


16

Pyth, 24 байти

L-b*/bJ+3^T11Jy*uy^GT11Q

Тестовий набір

Для цього використовується той факт, що ^ (p-2) mod p = a ^ -1 mod p.

По-перше, я вручну повторюю модуль для конкретного випадку моди 100000000003. Я використовую формулу a mod b = a - (a/b)*b, де /є floored поділ. Я генерую модуль з 10^11 + 3, використовуючи код +3^T11, потім зберігаю його J, потім використовую цю та вищезгадану формулу для обчислення b mod 100000000003 с -b*/bJ+3^T11J. Ця функція визначена як yз L.

Далі я починаю з вводу, потім беру його на десяту потужність і зменшую мод 100000000003, і ​​повторюю це 11 разів. y^GT- це код, виконаний на кожному кроці, і uy^GT11Qвиконує його 11 разів, починаючи з введення.

Тепер у мене є Q^(10^11) mod 10^11 + 3, і я хочу Q^(10^11 + 1) mod 10^11 + 3, тому я помножую на вхід на *, зменшуючи його мод 100000000003 з yостаннім часом, і виводять.


Дуже приємно насправді!

Я здогадуюсь, що мені вже пізно затягувати тестові справи ....

1
@Lembik Я б це робив у будь-якому випадку, але думки можуть відрізнятися. Це ваше завдання, змусьте його працювати так, як ви хочете.
isaacg

Як написано запитання, можливо, ви можете відмовитися від остаточного зменшення, хоча я попросив уточнити, чи потрібен результат <100000000003.
Ørjan Johansen

9

Haskell , 118 113 105 101 байт

Натхненний цим рішенням .

-12 від Ørjan Johansen

p=10^11+3
k b=((p-2)?b)b 1
r x=x-div x p*p
(e?b)s a|e==0=a|1<2=(div e 2?b$r$s*s)$last$a:[r$a*s|odd e]

Спробуйте в Інтернеті!

Haskell , 48 байт

Перепишіть це рішення . Хоча це досить швидко для тестового вектора, це рішення є занадто повільним для інших вхідних даних.

s x=until(\t->t-t`div`x*x==0)(+(10^11+3))1`div`x

Спробуйте в Інтернеті!


Дивовижно! Мені подобається експоненцію за допомогою підходу в квадраті.
isaacg

Найкоротшим рішенням стане щось на кшталт Спробуйте в Інтернеті! але я не думаю, що його продуктивність є прийнятною ...
bartavelle

(1) Це коротше , щоб gоператор (e?b)a s|...(2) Якщо при включенні aі sпісля цього ви можете зробити !в нон -оператора і вбудований yв нього. (3) Ви можете позбутися дорогого whereза допомогою lastтрюку ціною дублювання z. Спробуйте в Інтернеті!
Ørjan Johansen

Тепер це приємні трюки!
bartavelle

Ох, і |e==0=aпозбавляється від цього примхливого дублювання.
Ørjan Johansen

6

Брахілог , 22 байти

∧10^₁₁+₃;İ≜N&;.×-₁~×N∧

Спробуйте в Інтернеті!

На це знадобилося приблизно 10 хвилин для 1000000трохи іншої (і довшої) версії коду, яка була рівно в два рази швидшою (перевірено лише позитивні значення İзамість як позитивних, так і негативних). Тому для цього потрібно зайняти приблизно 20 хвилин.

Пояснення

Ми просто описуємо це Input × Output - 1 = 100000000003 × an integer, і нехай Outputдля нас знайдеться арифметика обмеження .

∧10^₁₁+₃                   100000000003
        ;İ≜N               N = [100000000003, an integer (0, then 1, then -1, then 2, etc.)]
            &;.×           Input × Output…
                -₁         … - 1…
                  ~×N∧     … = the product of the elements of N

Нам технічно не потрібна явна маркування , однак якщо ми не використовуємо її, не перевірятимемо випадок N = [100000000003,1](тому що це часто марно), це означає, що це буде дуже повільним для введення, 2наприклад, тому що йому потрібно буде знайти друге найменше ціле число замість першого.


1
Нічого собі, я ніколи не очікував би арифметики обмеження, щоб зняти це. Дивовижно!
isaacg

1
@isaacg Швидкість цього, на жаль, повністю залежить від вартості İ, тому для великих продуктів це все ще досить повільно.
Фаталізувати

Оновлено питання. Чи завжди ваш код займає менше 30 хвилин?

6

Пітон, 53 51 49 58 53 49 байт

-2 байта завдяки орлп
-2 байта завдяки офіалаімму
4 байти завдяки Феліпе Нарді Батіст
-3 байта завдяки Ісаакг
-1 байт завдяки Шріану Йохансен
-2 байту завдяки Федеріко Полоні

x=input()
t=1
while t-t/x*x:t+=3+10**11
print t/x

Спробуйте в Інтернеті!

На це мені знадобилося ~ 30 хвилин. Моє рішення - почати з першого числа, яке буде модифікувати 1. Це число дорівнює 1. Якщо його ділиться на х, то у - це число, поділене на х. Якщо ні, додайте до цього числа 10000000003, щоб знайти друге число, мод 1000000003 якого дорівнює 1, і повторити.


Перше число, яке зміниться на 1, - 1 ...
orlp

@orlp lol дякую Це врятувало мене 2 байти :)
Zachary Cotton

Цікаво, що в TIO це швидко для всіх тестових випадків, але трохи випадкових ударів клавіатури дало мені час, 421385994який вийшов.
Ørjan Johansen

@ ØrjanJohansen Хороший спати.

1
Якщо вам потрібно bлише один раз, чому б не жорстко кодувати це?
Федеріко Полоні

5

JavaScript (ES6), 153 143 141 байт

Натхненна цією відповіддю від math.stackexchange.com .

Рекурсивна функція, заснована на алгоритмі Евкліда.

f=(n,d=(F=Math.floor,m=1e11+3,a=1,c=n,b=F(m/n),k=m-b*n,n>1))=>k>1&d?(e=F(c/k),a+=e*b,c-=e*k,f(n,c>1&&(e=F(k/c),k-=e*c,b+=e*a,1))):a+d*(m-a-b)

Модуло реалізується за допомогою обчислення:

quotient = Math.floor(a / b);
remainder = a - b * quotient;

Оскільки коефіцієнт також потрібен, робити це таким чином насправді має певний сенс.

Тестові кейси


Вам потрібні лише 64-бітні підлоги за останній час, щоб ви могли замінити інші на 0 | x / y та видалити декларацію
Oki

5

C ++ 11 (GCC / Clang, Linux), 104 102 байти

using T=__int128_t;T m=1e11+3;T f(T a,T r=1,T n=m-2){return n?f(a*a-a*a/m*m,n&1?r*a-r*a/m*m:r,n/2):r;}

https://ideone.com/gp41rW

Унгольф, заснований на теоремі Ейлера та бінарній експоненції.

using T=__int128_t;
T m=1e11+3;
T f(T a,T r=1,T n=m-2){
    if(n){
        if(n & 1){
            return f(a * a - a * a / m * m, r * a - r * a / m * m, n / 2);
        }
        return f(a * a - a * a / m * m, r, n / 2);
    }
    return r;
}

ISO C ++ вимагає, longщоб він був принаймні 32-розрядним, тому він не може обов'язково містити 1e11 + 3. Це 32-розрядна версія у x86-64 Windows. long64-розрядний тип на Linux x86-64 (та інших ОС, що використовують SystemV ABI). Щоб бути повністю портативним, вам потрібно буде використовувати long long, що гарантує, що принаймні 64-розрядні з моменту C ++ 11 .
Пітер Кордес

__int128_tне здається стандартним C ++, це здається, що це розширення gcc, було б здорово, якби ви заявили це як мову (C ++ 11 + gcc).
Фелікс Домбек

3
Це не повинен бути сайт експертів C ++, я сподівався, що ніхто цього не помітить.
SteelRaven

@PeterCordes Code Golf не потрібно бути портативним або навіть добре сформованим, він просто повинен працювати над однією реалізацією.
aschepler

1
@aschepler: Я знаю, тому я сказав : «Ви б потрібно». Я подумав, що було б корисно вказати, на якій платформі вона / не працюватиме, на випадок, якщо хтось спробує її і натрапив на проблему.
Пітер Кордес

4

Математика, 49 байт

x/.FindInstance[x#==k(10^11+3)+1,{x,k},Integers]&

Скільки часу потрібно пробігти?

Менш ніж 0,001 на моєму комп’ютері (для випадку 2 ^ 40-1)
Keyu Gan


1

Рубін , 58 байт

Наразі використовує застосування Ісаакг малої теореми Ферма, поки я закінчую розробку часу на грубі сили.

->n,x=10**11+3{i=n;11.times{i**=10;i-=i/x*x};i*=n;i-i/x*x}

Поточна версія перебором, яка становить 47 байт , але може бути це занадто повільно:

->n,x=10**11+3{(1..x).find{|i|i*=n;i-i/x*x==1}}

Спробуйте в Інтернеті!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.