Вычислить инверсию целого числа по модулю 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 нормально?
user253751

@immibis Это выглядит хорошо.

тег: ограниченный код?
Фелипе Нарди Батиста,

1
Что особенного 100000000003? (просто интересно)
NoOneIsHere

1
@Lembik. В таком случае, не могли бы вы упомянуть это требование, что у <100000000003 в вопросе?
Исаак

Ответы:


16

Pyth, 24 байта

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

Тестирование

Это использует тот факт, что ^ (р-2) мод р = а ^ -1 мод р.

Во-первых, я вручную переопределяю модуль, для конкретного случая мода 100000000003. Я использую формулу a mod b = a - (a/b)*b , где /находится этажное деление. Я генерирую модуль с 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 Я бы так и сделал, но мнения могут отличаться. Это ваша задача, заставить ее работать так, как вы хотите.
Исаак

При написании вопроса возможно, что вы можете отбросить окончательное сокращение, хотя я попросил уточнить, требуется ли результат <100000000003.
Орджан Йохансен,

9

Haskell , 118 113 105 101 байт

Вдохновлен этим решением .

-12 от Орьяна Йохансена

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

Попробуйте онлайн!


Потрясающе! Мне нравится возведение в степень по принципу возведения в квадрат.
Исаак

Самое короткое решение - что-то вроде Попробуй онлайн! но я не думаю, что его производительность приемлема ...
Bartavelle

(1) Это короче , чтобы gоператор (e?b)a s|...(2) Если при включении aи sпосле этого вы можете сделать !в нон -оператора и встроенный yв него. (3) Вы можете избавиться от дорогого whereс помощью lastтрюка, за счет дублирования z. Попробуйте онлайн!
Орджан Йохансен

Теперь это хорошие трюки!
Bartavelle

Ох, и |e==0=aизбавляется от этого надоедливого дублирования.
Орджан Йохансен

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
Ух ты, я бы никогда не ожидал, что арифметика с ограничениями осуществит это. Потрясающе!
Исаак

1
@isaacg Скорость этого, к сожалению, полностью зависит от стоимости İ, так что это все еще довольно медленно для больших продуктов.
Фатализировать

Обновил вопрос. Ваш код всегда занимает менее 30 минут?

6

Python, 53 51 49 58 53 49 байтов

-2 байта благодаря orlp
-2 байта благодаря officialaimm
-4 байта благодаря Фелипе Нарди Батисту
-3 байта благодаря isaacg
-1 байту благодаря Орджану Йохансену
-2 байта благодаря Федерико Полони

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

Попробуйте онлайн!

Мне потребовалось ~ 30 минут, чтобы понять это. Мое решение состоит в том, чтобы начать с первого числа, которое изменится на 1. Это число равно 1. Если оно делится на x, то y это число, деленное на x. Если нет, добавьте 10000000003 к этому номеру, чтобы найти второе число, мод 1000000003 будет равен 1, и повторите.


Первое число, которое будет мод 1: 1 ...
orlp

@ или LOL спасибо. Это спасло мне 2 байта :)
Захари Коттон

Интересно, что на TIO это быстро для всех тестовых случаев, но немного случайное нажатие клавиатуры дало мне 421385994время ожидания.
Орджан Йохансен

@ Ø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

Ungolfed, основанный на теореме Эйлера и двоичном возведении в степень.

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. longэто 64-битный тип в x86-64 Linux (и других ОС, использующих SystemV ABI). Таким образом, чтобы быть полностью переносимым, вам нужно использовать long long, который гарантированно будет как минимум 64-битным начиная с C ++ 11 .
Питер Кордес

__int128_tне кажется стандартным C ++, это, кажется, расширение gcc, было бы здорово, если бы вы указали это как язык (C ++ 11 + gcc).
Феликс Домбек

3
Это не должен быть сайт экспертов C ++, я надеялся, что никто не заметит.
SteelRaven

@PeterCordes Code Golf не должен быть портативным или даже правильно сформированным, он просто должен работать над одной реализацией.
aschepler

1
@aschepler: Я знаю, поэтому я сказал : «Вы бы нужно». Я подумал, что было бы полезно указать, на какой платформе он будет / не будет работать, если кто-нибудь попробует и столкнется с проблемой.
Питер Кордес

4

Mathematica, 49 байтов

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

Сколько времени это займет, чтобы бежать?

Менее 0,001 с на моем компьютере (для случая 2 ^ 40-1)
Кейу Ган,


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.