Modüler ters hesapla


16

İki pozitif sayı verildiğinde xve nile x<2^n, hesaplamak için mümkün olan en kısa fonksiyonu yazın x^-1 mod 2^n. Başka bir deyişle, yböyle bulun x*y=1 mod 2^n.

İşleviniz en azından makul bir sürede tamamlanmalıdır n=64, bu nedenle kapsamlı arama çalışmaz.

Tersi yoksa, bunu arayana bir şekilde belirtmelisiniz (bir istisna atın, bir sentinel değeri döndürün, vb.).

Nereden başlayacağınızı merak ediyorsanız Genişletilmiş Öklid Algoritmasını deneyin .


bu bazı matematik yazılımlarında tek bir ifade olacak
st0le

1
@ st0le: Doğru ve böyle sistemlerde böyle bir işlevi kullanmanıza izin verilmez. :-D
Chris Jester-Young

Yanıtlar:


2

Python 95 89

csenin fonksiyonun. Tersi yoksa 0 döndürür (yani x eşit olduğunda).

p=lambda x,y,m:y and p(x,y/2,m)**2*x**(y&1)%m or 1
c=lambda x,n:[0,p(x,2**n-1,2**n)][x%2]

3

Python, 29 bayt

lambda x,n:pow(x,2**n-1,2**n)

Bu çift x için 0 döndürür . Euler teoremini, Python'un yerleşik hızlı modüler üstellemesi yoluyla 2 ^ n - 1'in 2 ^ ( n - 1) - 1 ile bölünebileceği gözlemiyle kullanır . Bu, yaklaşık bir saniyeden fazla sürmeye başladığı 7000'e kadar n için yeterince hızlıdır .


2

Mathematica - 22

f=PowerMod[#,-1,2^#2]&

f[x,n]döner yile x*y=1 mod 2^naksi halde,x is not invertible modulo 2^n


2

GolfScript (23 karakter)

{:^((1${\.**2^?%}+*}:f;

Var olmayan bir tersin nöbetçi sonucu budur 0.

Bu, Euler teoreminin basit bir uygulamasıdır . , yanixφ(2n)1(şık2n)x-1x2n-1-1(şık2n)

Ne yazık ki bu doğrudan hesaplamak için çok büyük bir üstel, bu yüzden bir döngü kullanmalı ve döngü içinde modüler azaltma yapmalıyız. Yinelemeli adım ve temel durum bir seçim: ya ilex2k-1=(x2k-1-1)2xxk=1

{1\:^(@{\.**2^?%}+*}:f;

veya k=2ile

{:^((1${\.**2^?%}+*}:f;

Başka bir yaklaşım üzerinde çalışıyorum, ancak nöbetçi daha zor.

Temel gözlem, tersi inşa edebilmemizdir: sonra ve eğer garip Elimizdeki . (Eğer ikna değilseniz, iki vakayı ayrı ayrı kontrol edin). Böylece herhangi bir uygun temel durumda başlayabilir ve dönüşümünü uygun sayıda uygulayabiliriz .xy1(şık2k-1)xy{1,1+2k-1}(şık2k)xx(y+xy-1)1(şık2k)y'=(x+1)y-1

beri indüksiyonla0x1(şık20)

x(1-(x+1)nx)1(şık2n)

burada tersi geometrik dizinin toplamıdır. Şapkadan tavşan efektinden kaçınmak için derivasyonu gösterdim: bu ifade verildiğinde bunu görmek kolaydır (köşeli parantez değerinin bir tamsayı toplamı olarak türetilmesinden sonra gelen bir tam sayı olduğu göz önüne alındığında) sekans) eşitse soldaki ürün doğru eşdeğerlik sınıfında olmalıdır .x+1

19 karakterlik fonksiyon

{1$)1$?@/~)2@?%}:f;

tersi olan girdiler için doğru cevaplar verir. Ancak, eşit olduğunda o kadar da basit değildir . Bulduğum potansiyel olarak ilginç bir seçenek, eklemek yerine eklemek .xx&11

{1$.1&+1$?@/~)2@?%}:f;

Bu, veya sentinel değerleri veriyor gibi görünüyor , ancak henüz bunu kanıtlamadım.02n-1

Bundan başka bir adım, biz bir sentinel sağlamak olabilir alarak ekspresyonunu değiştirerek çift sayı için içine :01-(x+1)n1-1n

{1$.1&*)1$?@/~)2@?%}:f;

Bu, kod uzunluğu için Euler teoreminin doğrudan uygulanmasına bağlıdır, ancak büyük için daha kötü performans gösterecektir . Eğer argümanları başka bir yoldan alırsak, bir karakteri kaydedebilir ve 22 karakter elde edebiliriz :nn x f

{..1&*)2$?\/~)2@?%}:f;

1

Ruby - 88 karakter

İşlevi kullanın f.

def e a,b;a%b==0?[0,1]:(x,y=e(b,a%b);[y,x-(y*(a/b))])end
def f x,n;e(x,2**n)[0]*(x%2)end

Bağlantılı wiki sayfasındaki özyinelemeli işlev, hata durumunda 0 döndürür.


E: 'yi satır içine alarak bazı karakterleri kaydedebilirsiniz (e=->a,b{...})[x,2**n][0]. a%b<1Bunun yerine test ederek bir karakteri de kaydedebilir a%b==0.
histokrat


1

Pyth , 9 bayt

.^Et^2Q^2

Burada deneyin!

Girişi ters sırada alır. Veya, 9 çok bayt: .^EtK^2QK.

açıklama

. ^ Et ^ 2Q ^ 2 - Tam program.

. ^ - Pow işlevi. Aynı şey Python (pow) için de geçerlidir.
  E - İkinci giriş.
    ^ 2Q - Ve 2 ^ ilk giriş.
   t - Azalan.
       ^ 2 - Ve tekrar 2 ^ ilk giriş.

0

GAP, 39 bayt

f:=function(x,n)return 1/x mod 2^n;end;

f(x,n)xmodulo'nun tersini döndürür 2^nve bir hata mesajı verir

Error, ModRat: for <r>/<s> mod <n>, <s>/gcd(<r>,<s>) and <n> must be coprime

tersi yoksa.

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.