Modüler çarpımsal ters


22

Göreviniz iki tam sayı vermek ave bvarsa, bir modulo b'nin modüler çarpımsal tersini hesaplamaktır.

aModülün modüler tersi, böyle bbir sayıdır . Bu sayı benzersiz modülo olan herhangi çifti için ve . Sadece en büyük ortak bölen kişi ve varsa, var olur .cac ≡ 1 (mod b)babab1

Konuyla ilgili daha fazla bilgiye ihtiyaç duyarsanız, modüler çarpımsal ters için Wikipedia sayfasına bakılabilir.

Giriş ve çıkış

Giriş, iki tam sayı veya iki tamsayının listesi olarak verilir. Programınız, tek bir sayı, aralıktaki modüler çarpımsal tersi 0 < c < bveya ters olmadığını gösteren bir değer vermelidir . Değer, aralıktaki sayı dışında herhangi bir şey (0,b)olabilir ve ayrıca bir istisna olabilir. Bununla birlikte, değerin ters olmadığı durumlarda aynı olmalıdır.

0 < a < b varsayılabilir

kurallar

  • Program bir noktada bitmeli ve her test vakasını 60 saniyeden daha kısa sürede çözmelidir.
  • Standart boşluklar uygulanır

Test durumları

Aşağıdaki test durumları aşağıdaki formatta verilmiştir. a, b -> output

1, 2 -> 1
3, 6 -> Does not exist
7, 87 -> 25
25, 87 -> 7
2, 91 -> 46
13, 91 -> Does not exist
19, 1212393831 -> 701912218
31, 73714876143 -> 45180085378
3, 73714876143 -> Does not exist

puanlama

Bu kod golf, yani her dil için en kısa kod kazanır.

Bu ve bu benzer sorular, ancak her ikisi de özel durumlar istiyor.


6
Fermat'ın Küçük Teoreminden, eğer a'nın çarpımsal tersi, eğer varsa, etkin bir şekilde (phi (b) -1) mod b olarak hesaplanabiliyor, burada phi Euler'in çözme işlevidir: phi (p0 ^ k0 * p1 ^) k1 * ...) = (p0-1) * p0 ^ (k0-1) * (p1-1) * p1 ^ (k1-1) * ... Daha kısa kodlara yol açtığını söyleme :)
ngn

1
@ Jenny_mathy Ek girdi almak genellikle izin verilmez.
Bay Xcoder

3
Zorlayıcı görünen altı yanıtı ve tüm test vakalarını 60 saniyede çalıştırma ihtimalinin düşük olduğunu düşünüyorum (bazıları önce bir yığın ya da bellek hatası veriyor).
Ørjan Johansen

1
@ngn: Fermat'ın Küçük Teoremi'ni (FLT) Euler'ın iyileştirilmesiyle karıştırdın. Fermat, Euler phi fonksiyonunu bilmiyordu. Ayrıca, FLT ve Euler'in gelişimi sadece eğer gcd (a, b) = 1 ise geçerlidir. Sonunda, yazdığınız biçimde, "a ^ (\ phi (b) -1) mod b" 1 ile uyumludur; ^ (- 1). Bir ^ (- 1) almak için, bir ^ (\ phi (b) -2) mod b kullanın.
Eric Towers

1
@EricTowers Euler bir sonucudur. "Gcd (a, b) = 1" ile ilgili olarak - "eğer [varsa]" dedim. Phi (b) -2 hakkında emin misiniz?
ngn

Yanıtlar:


11

Mathematica, 14 bayt

Zorunlu Mathematica yerleşik :

ModularInverse

İki argüman ( ave b) alan ve varsa bir mod b'nin tersini döndüren bir fonksiyondur . Değilse, hatayı döndürür ModularInverse: a is not invertible modulo b..


7

JavaScript (ES6), 79 73 62 61 bayt

falseTersi yoksa döndürür .

Genişletilmiş Öklid algoritmasını kullanır ve neredeyse tüm test durumlarını anında çözer.

f=(a,b,c=!(n=b),d=1)=>a?f(b%a,a,d,c-(b-b%a)/a*d):b<2&&(c+n)%n

Test durumları


F fonksiyonunun adını f (c, a, b = 0, d = 1, n = a) => c? F (a% c, c, d, b- ( aa% c) / c * d, n): a <2 && (b + n)% n?
RosLuP

@RosLup f(x,y), functionanahtar kelime tarafından açıkça belirtilmediği sürece , her zaman bir işlev çağrısı olarak ayrıştırılır . Öte yandan, isimsiz bir ok işlevi olarak bildirilir (x,y)=>somethingve f=(x,y)=>somethingişlevi fdeğişkene atar .
Arnauld

4

Jöle , 2 bayt

æi

Çevrimiçi deneyin!

Bu modüler ters için bir yerleşik kullanır ve hiçbir modüler ters için 0 döndürür.

Jöle , 7 bayt

R×%⁸’¬T

Çevrimiçi deneyin!

Modüler bir ters değil üzerinde boş kümeyi (boş dize olarak temsil edilir) çıkar. En büyük test durumları için TIO’da bellek yetersiz kalıyor, ancak yeterli bellek sağlandığında çalışması gerekiyor.

Nasıl çalışır

R×%⁸’¬T  
R        Generate range of b
 ×       Multiply each by a
  %⁸     Mod each by b
    ’    Decrement (Map 1 to 0 and all else to truthy)
     ¬   Logical NOT
      T  Get the index of the truthy element.

Daha büyük test senaryoları için çalışmak istiyorsanız, hafızadan ziyade çok zaman gerektiren bu (nispeten ağrısız) versiyonunu deneyin:

Jöle, 9 bayt

×⁴%³’¬ø1#

Çevrimiçi deneyin!

Nasıl çalışır

×⁴%³’¬ø1#
        #   Get the first
      ø1      one integer
            which meets:
×⁴            When multiplied by a
  %³          And modulo-d by b
    ’         Decrement
     ¬        Is falsy

4

Python 2 bayt

f=lambda a,b:a==1or-~b*f(-b%a,a)/a

Çevrimiçi deneyin!

Tekrarlayan fonksiyon veren True için print f(1,2)ben kabul edilebilir olduğuna inanıyorum, ve geçersiz girişler için hatalar.

Biz bulmaya çalışıyoruz x içinde ax1(modb) .

Bu ax1=kb olarak yazılabilir, burada k bir tamsayıdır.

alma moda Bunun verir1kb(moda) . Eksi Hareketli verirkb1(moda)k için çözmemiz gereken yerler.

İlk senaryonun nasıl göründüğünü görünce , işlevini f ( - b % a , a ) ile çağırarak k için çözmemize izin verin.f(b%a,a) (Python, modulo için negatif bir argümanla pozitif değerler verdiği için çalışır).

Program , 1 olana kadar devam a , yalnızca orijinal a ve b birbirlerinin (yani, çarpımsal bir ters varsa) veya 0'a bölünmenin neden olduğu bir hatayla sonuçlanır.

Bu değer k denklemde ikame edilebilir ax1=kb vermek üzere x olarak kb+1a .


3

R + numaraları , 15 bayt

numbers::modinv

modları ters NAolanlar için döner .ab

R-Fiddle, denemek için!

R , 33 bayt (rekabet etmeyen)

Bu bgerçekten büyük bir 32*bbit vektörü oluşturduğu için çok büyük başarısızlık gösterir .

function(a,b)which((1:b*a)%%b==1)

Çevrimiçi deneyin!

İade integer(0)olanlar için (boş bir liste) atersleri mod olmadan b.


3

Mathematica, 18 bayt

PowerMod[#,-1,#2]&

giriş

[31, 73714876143]


3

Python 2 , 51 49 54 53 51 49 bayt

Officialaimm sayesinde
-1 bayt Shaggy sayesinde -1 bayt

a,b=input()
i=a<2
while(a*i%b-1)*b%a:i+=1
print+i

Çevrimiçi deneyin!

0Çözüm olmadığında yazdırır .


1
Çıkışlar 0için a=1ve b=2; Test durumlarından çıktı 1.
Shaggy


1
Shaggy'nin belirttiği gibi, başarısız olur2, 1
Bay Xcoder

@Shaggy şimdi çalışmalı
Rod

Bu, giriş için 60 saniye içinde (TIO'da) bir cevap döndüremez 31,73714876143.
Ilmari Karonen

3

Japt , 9 8 bayt

Girişleri ters sırada alır. Eşleşmeden -1çıktı. Büyük tamsayı büyüdükçe hışırdar.

Ç*V%UÃb1

Dene

  • ETH sayesinde hatalı ve çok açık bir alana işaret eden 1 bayt kurtarıldı.

Test girişi 73714876143,31, Firefox'ta yetersiz bir bellek hatası veriyor gibi görünüyor (ve Chromium'u çökertiyor). Bunun geçerli bir cevap olduğunu sanmıyorum.
Ilmari Karonen

@IlmariKaronen: Çözümümdeki gerçeği açıkça belirttim. Kod golf amacıyla sınırsız bellek varsayabiliriz, böylece bellek sorunları ve çökmeler bu çözümü geçersiz kılmaz.
Shaggy

1
Maalesef bellek sorunları da, kodunuzun test durumlarını 60 saniyede, zorlukların öngördüğü şekilde çözüp çözemeyeceğini söylemeyi imkansız kılıyor. Kaza olmamasını sağlayacak yeterli bellek olsa bile olmayacağından şüpheliyim, ancak programı gerçekten o kadar uzun süre çalıştırabilecek bir bilgisayar olmadan kesin olarak söylemenin bir yolu yok.
Ilmari Karonen


2

Python 3 , 49 bayt

lambda a,b:[c for c in range(b)if-~c*a%b==1][0]+1

Çevrimiçi deneyin!

Python 3 , 50 bayt

lambda a,b:[c for c in range(1,b+1)if c*a%b==1][0]

Çevrimiçi deneyin!

Bu IndexError: list index out of rangekurallar tarafından izin verildiği gibi modüler çarpımsal bir ters olmadığında ortaya çıkar.


Bu, giriş 31,73714876143için 60 saniye içinde bir sonuç döndüremez (TIO'da).
Ilmari Karonen

@IlmariKaronen Makinemde 56 saniyede bitiyor gibi görünüyor (Macbook Pro '15)
Bay Xcoder

2

8 , 6 bayt

kod

invmod

açıklama

invmoda, modulo tersinin değerini hesaplayan 8. bir kelimedir b. DönernullTaşma ya da diğer hatalarla .

Kullanım ve test durumları

ok> 1 2 invmod .
1
ok> 3 6 invmod .
null
ok> 7 87 invmod .
25
ok> 25 87 invmod .
7
ok> 2 91 invmod .
46
ok> 13 91 invmod .
null
ok> 19 1212393831 invmod .
701912218
ok> 31 73714876143 invmod .
45180085378
ok> 3 73714876143 invmod .
null


2

J , 28 bayt

4 :'(1=x+.y)*x y&|@^<:5 p:y'

Çevrimiçi deneyin!

Euler teoremini kullanır . Tersi yoksa 0 döndürür.

açıklama

4 :'(1=x+.y)*x y&|@^<:5 p:y'  Input: a (LHS), b (RHS)
4 :'                       '  Define an explicit dyad - this is to use the special
                              form `m&|@^` to perform modular exponentiation
                          y   Get b
                      5 p:    Euler totient
                    <:        Decrement
             x                Get a
                   ^          Exponentiate
               y&|@             Modulo b
       x+.y                   GCD of a and b
     1=                       Equals 1
            *                 Multiply

2

Pyth , 10 bayt

@Jakube sayesinde 3 bayt kaydedildi .

xm%*szdQQ1

Burada dene!

Returns -1 for no multiplicative inverse.

Code Breakdown

xm%*szdQQ1      Let Q be the first input.
 m      Q       This maps over [0 ... Q) with a variable d.
   *szd         Now d is multiplied by the evaluated second input.
  %    Q        Now the remained modulo Q is retrieved.
x        1      Then, the first index of 1 is retrieved from that mapping.

Pyth, 15 13 bytes

KEhfq1%*QTKSK

Throws an exception in case no multiplicative inverse exists.

Try it here!

Pyth, 15 bytes

Iq1iQKEfq1%*QTK

This adds lots of bytes for handling the case where no such number exists. The program can be shortened significantly if that case would not need to be handled:

fq1%*QTK

Try it here!


2 bytes saved with KExm%*QdKK1
Jakube

Or 3 bytes if you swap the order of inputs: xm%*szdQQ1
Jakube

@Jakube Thanks a lot, editing!
Mr. Xcoder

How does this work?
Kritixi Lithos

@Cowsquack Tamamen ilkel bir kod dökümü ekledim, ancak tam bir açıklama eklemek için zamanım yok. Umarım şimdilik yeterince açıktır ancak yakında daha ayrıntılı bir açıklama eklemeye çalışacağım.
Bay Xcoder

1

C (gcc) , 115 bayt

#define L long long
L g(L a,L b,L c,L d){return a?g(b%a,a,d-b/a*c,c):b-1?0:d;}L f(L a,L b){return(g(a,b,1,0)+b)%b;}

Çevrimiçi deneyin!

Genişletilmiş Öklid algoritması, özyinelemeli sürüm

C (gcc) , 119 bayt

long long f(a,b,c,d,t,n)long long a,b,c,d,t,n;{for(c=1,d=0,n=b;a;a=t)t=d-b/a*c,d=c,c=t,t=b%a,b=a;return b-1?0:(d+n)%n;}

Çevrimiçi deneyin!

Genişletilmiş Öklid algoritması, yinelemeli sürüm


1

C (gcc) , 48 110 104 bayt

#define f(a,b)g(a,b,!b,1,b)
long g(a,b,c,d,n)long a,b,c,d,n;{a=a?g(b%a,a,d,c-(b-b%a)/a*d):!--b*(c+n)%n;}

Çevrimiçi deneyin!

Bu, 60 saniye içinde tüm girişlerle (uzun süre içinde sığacak şekilde) çalışmalıdır.

Edit. I'm already abusing the n variable so I might as well assume that gcc puts the first assignment in %rax.


1
Alas, this gives wrong results even for fairly small inputs due to integer overflow inside the loop. For example, f(3,1000001) returns 717, which is obviously nonsense (the correct answer is 333334). Also, even if this bug was fixed by using a wider integer type, this brute-force approach would certainly time out for some of the larger test cases given in the challenge.
Ilmari Karonen


0

Axiom, 45 bytes

f(x:PI,y:PI):NNI==(gcd(x,y)=1=>invmod(x,y);0)

0 for error else return z with x*z Mod y =1


0

Python 2, 52 bytes

-3 bytes thanks to Mr. Xcoder.

f=lambda a,b,i=1:i*a%b==1and i or i<b and f(a,b,i+1)

Try it online!

Outputs False on no solution and errors out as b gets larger.

Embedded TIO

I'm just testing out iframes in Stack Snippets and they work absolutely fantastic.


I'm not certain this works, can't i*a%b be 0?
Wheat Wizard

Fails with "maximum recursion depth exceeded" error for input (31,73714876143).
Ilmari Karonen

0

JavaScript (ES6), 42 41 39 38 bytes

Outputs false for no match. Will throw a overflow error as the second number gets to be too large.

x=>y=>(g=z=>x*z%y==1?z:z<y&&g(++z))(1)

0

Jelly, 27 bytes

²%³
⁴Ç⁹Сx⁸
ÆṪ’BṚçL$P%³×gỊ¥

Try it online!

Uses Euler's theorem with modular exponentiation. Since Jelly doesn't have a builtin to perform modular exponentiation, it had to be implemented, and it took most of the bytes.


0

Axiom, 99 bytes

w(a,b,x,u)==(a=0=>(b*b=1=>b*x;0);w(b rem a,a,u,x-u*(b quo a)));h(a,b)==(b=0=>0;(b+w(a,b,0,1))rem b)

it use the function h(); h(a,b) return 0 if error [not exist inverse] otherwise it return the z such that a*z mod b = 1 This would be ok even if arguments are negative...

this would be the general egcd() function that retunr a list of int (so they can be negative too)

egcd(aa:INT,bb:INT):List INT==
   x:=u:=-1   -- because the type is INT
   (a,b,x,u):=(aa,bb,0,1)
   repeat
      a=0=>break
      (q,r):=(b quo a, b rem a)
      (b,a,x,u):=(a,r,u,x-u*q)
   [b,x, (b-x*aa)quo bb]

this is how use it

(7) -> h(31,73714876143)
   (7)  45180085378
                                                    Type: PositiveInteger

i find the base algo in internet from https://pastebin.com/A13ybryc

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.