Doğal olarak doğrusal Diophantine denklemleri


13

Lineer bir Diofant denklem iki değişken bir şekilde bir denklemdir = C ile ax + , burada bir , b ve c sabit tamsayı ve x ve y değişken tamsayıdır.

Birçok doğal olarak oluşan Diophantine denklemi için, x ve y negatif olmayan miktarları temsil eder.

Görev

Giriş olarak a , b ve c katsayılarını kabul eden ve rasgele bir çift doğal sayı (0, 1, 2,…) x ve y denklemini doğrulayan + böyle bir çift varsa + = = c denklemini doğrulayan bir program veya işlev yazın bulunmaktadır.

Ek kurallar

  • Giriş ve çıkış için, girişe herhangi bir kod yerleştirmediğiniz sürece, yalnızca istenen tam sayıları ve isteğe bağlı olarak dilinizin dizi / liste / matris / tuple / vektör gösterimini içeren herhangi bir biçimi seçebilirsiniz.

  • A ve b katsayılarının sıfır olmadığını varsayabilirsiniz .

  • Kodunuz -2 60 ile 2 60 arasında bir tam sayı üçlüsü için çalışmalıdır ; makinemde bir dakikadan kısa sürede bitmesi gerekiyor (Intel i7-3770, 16 GiB RAM).

  • Diophantine denklemlerini çözen ve böylece Mathematica'nın FindInstanceveya gibi bu görevi önemsizleştiren herhangi bir yerleşik kullanamazsınız FrobeniusSolve.

  • Bununla birlikte, zaman sınırına uyduğu ve çıktısının geçerli bir çözümle karıştırılamadığı sürece hiçbir çözüm bulunamazsa kodunuz istediğiniz gibi davranabilir.

  • Standart kuralları geçerlidir.

Örnekler

  1. Aşağıdaki örnekler, 2x + 3y = 11 denklemi için geçerli iki G / Ç'yi göstermektedir ; bu, tam olarak iki geçerli çözeltiye sahiptir ( (x, y) = (4,1) ve (x, y) = (1,3) ).

    Input:  2 3 11
    Output: [4 1]
    
    Input:  (11 (2,3))
    Output: [3],(1)
    
  2. 2x + 3y = 2 olan tek geçerli çözüm çifti (x, y) = (1,0) ' dır .

  3. Aşağıdaki örnekler , geçerli çözümü olmayan 2x + 3y = 1 denklemi için geçerli G / Ç'yi göstermektedir .

    Input:  (2 3 1)
    Output: []
    
    Input:  1 2 3
    Output: -1
    
    Input:  [[2], [3], [1]]
    Output: (2, -1)
    
  4. İçin , (a, b, c) = (1152921504606846883, -576460752303423433, 1) , tüm doğru çözeltiler (x, y) bu tatmin - (x, y) = (bn, 271275648142787502 +, bir 135637824071393749) bir negatif olmayan bir tamsayı için n .


Negatif olmayan tamsayılara biraz daha fazla vurgu yapmak iyi olabilir ve ikinci örneğin aslında bir çözümü olmadığını düşünüyorum.
Sp3000

intput 1 2 3 geçerli bir çıktıya sahip olsa da ... [1, 1]
Jack Ammo

@JackAmmo: İkinci kod bloğundaki tüm örnekler 2x + 3y = 1'e karşılık gelir .
Dennis

Axe + bx = k'da, çözümün x> = 0 ve y> = 0 olması gerektiğini anlamak gibi görünüyor. Öyleyse böyle x, y> = 0 38 * x + 909 * y = 3'ün çözümleri?
RosLuP

Böyle bir durumda, muhtemelen var olmayan bir çözümü geri döndürmek zorundayım ...
RosLuP

Yanıtlar:


6

Pyth, 92 bayt

I!%vzhK%2u?sm,ed-hd*ed/F<G2cG2@G1G+~Q,hQ_eQj9 2)J*L/vzhKtKeoSNm-VJ/RhK_*LdQsm+LdtM3/V*LhK_JQ

Oldukça canavar.

Çevrimiçi deneyin: Gösteri . Girdi biçimi c\n[a,b]ve çıktı biçimi [x,y].

Tamsayı çözümünün olmaması durumunda, hiçbir şey yazdırmayacağım ve doğal tamsayı çözümünün olmaması durumunda, rastgele bir tamsayı çözümü basacağım.

Açıklama (Genel Bakış)

  1. İlk önce ax + by = gcd(a,b)Genişletilmiş Öklid algoritmasını kullanarak denkleme tamsayı bir çözüm bulacağım .

  2. Sonra bir tamsayı çözümü elde etmek için çözümü (benim çarpma ave bile c/gcd(a,b)) değiştireceğim ax + by = c. Bu c/gcd(a,b)bir tamsayı ise çalışır . Aksi takdirde bir çözüm yoktur.

  3. Diğer tüm tamsayı çözeltiler formuna sahip a(x+n*b/d) + b(y-n*a/d) = c olan d = gcd(a,b)tamsayı n. İki eşitsizlikleri kullanma x+n*b/d >= 0ve y-n*a/d >= 0ben 6 olası değerleri belirleyebilir n. 6 tanesinin hepsini deneyeceğim ve çözümü en düşük katsayılı yazdıracağım.

Açıklama (Ayrıntılı)

İlk adım, denkleme tamsayı bir çözüm bulmaktır ax' + by' = gcd(a,b). Bu, genişletilmiş Öklid algoritması kullanılarak yapılabilir. Wikipedia'da nasıl çalıştığı hakkında bir fikir edinebilirsiniz . Tek fark, 3 sütun ( r_i s_i t_i) kullanmak yerine 6 sütun ( r_i-1 r_i s_i-1 s_i t_i-1 t_i) kullanacağım . Bu şekilde son iki satırı bellekte tutmak zorunda değilim, sadece son satırı.

K%2u?sm,ed-hd*ed/F<G2cG2@G1G+~Q,hQ_eQj9 2)   implicit: Q = [a,b] (from input)
                                     j9 2    convert 9 to base 2: [1,0,0,1]
                            + Q              add to Q => [a,b,1,0,0,1]
                                             this is the initial row
   u                                     )   start with G = ^ and update G repeatedly
                                             by the following expression, until
                                             the value of G doesn't change anymore
    ?                   @G1                    if G[1] != 0:
                     cG2                         split G into parts of 2
      m                                          map the parts d to:
       ,                                           the pair 
        ed                                           d[1]
          -hd*ed/F<G2                                d[0]-d[1]*G[0]/G[1]
     s                                           unfold
                                               else:
                           G                     G (don't change it, stop criterion for u)
 %2                                          take every second element
                                             we get the list [gcd(a,b),x',y']
K                                            store this list in K
                             ~Q,hQ_eQ        afterwards change Q to [Q[0],-Q[1]] = [a,-b]
                                             This will be important for the other parts. 

Şimdi bir çözüm bulmak istiyorum ax + by = c. Bu sadece ne zaman mümkündür c mod gcd(a,b) == 0. Bu denklem tatmin olmuşsa, ben sadece çarparak x',y'ile c/gcd(a,b).

I!%vzhK...J*L/vzhKtK   implicit: z = c in string format (from input)
  %vzhK                evaluated(z) mod K[0] (=gcd(a,b))
I!                     if not ^ than: 
             /vzhK        c/K[0]
           *L     tK      multipy ^ to each element in K[1:] (=[x',y'])
          J               and store the result in J, this is now [x,y]

İçin bir tamsayı çözümümüz var ax + by = c. Bildirim, o x, yya da her ikisi negatif olabilir. Yani amacımız bunları negatif olmayan biçime dönüştürmektir.

Diophantine denklemleri ile ilgili güzel bir şey, tüm çözümü sadece bir başlangıç ​​çözümü kullanarak tanımlayabilmemizdir. Eğer (x,y)diğer tüm çözümler formu olduğu, bir çözüm (x-n*b/gcd(a,b),y+n*a/gcd(a,b))için nbir tamsayı.

Bu nedenle bir n, nerede x-n*b/gcd(a,b) >= 0ve bulmak istiyoruz y+n*a/gcd(a,b >= 0. Bazı dönüşüm sonra iki eşitsizlikler ile bitirmek n >= -x*gcd(a,b)/bve n >= y*gcd(a,b)/a. Eşitsizlik simgesinin, potansiyel negatif aveya ile bölünme nedeniyle diğer yöne bakabileceğine dikkat edin b. Ben sadece söylemek, bu konuda o kadar umurumda değil ki biri sayısının -x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 11 eşitsizlik kesinlikle tatmin ve biri sayısının y*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1bir olduğu 2. eşitsizlik tatmin ntatmin her iki eşitsizlikler, 6 rakamlarından birini de yaptığı,.

Sonra (x-n*b/gcd(a,b),y+n*a/gcd(a,b))6 olası değerin tümü için yeni çözümler hesaplıyorum n. Ve çözümü en düşük değere sahip olarak yazdırıyorum.

eoSNm-VJ/RhK_*LdQsm+LdtM3/V*LhK_JQ
                               _J    reverse J => [y,x]
                           *LhK      multiply each value with K[0] => [y*gcd,x*gcd]
                         /V      Q   vectorized division => [y*gcd/a,-x*gcd/b]
                  m                  map each d of ^ to:
                      tM3              [-1,0,1]
                   +Ld                 add d to each ^
                 s                   unfold
                                     these are the possible values for n
    m                                map each d (actually n) of ^ to:
             *LdQ                      multiply d to Q => [a*n,-b*n]
            _                          reverse => [-b*n,a*n]
        /RhK                           divide by K[0] => [-b*n/gcd,a*n/gcd]
     -VJ                               vectorized subtraction with J
                                       => [x+b*n/gcd,y-a*n/gcd]
 oSN                                 order the solutions by their sorted order
e                                    print the last one

Sıralama düzenine göre sıralama şu şekilde çalışır. Örneği kullanıyorum2x + 3y = 11

6 çözümün her birini sıralıyorum (buna anahtar denir) ve orijinal çözümleri anahtarlarına göre sıralıyorum:

solutions: [1, 3], [4, 1], [7, -1], [-5, 7], [-2, 5], [1, 3]
keys:      [1, 3], [1, 4], [-1, 7], [-5, 7], [-2, 5], [1, 3]
sort by key:
solutions: [-5, 7], [-2, 5], [7, -1], [1, 3], [1, 3], [4, 1]
keys:      [-5, 7], [-2, 5], [-1, 7], [1, 3], [1, 3], [1, 4]

Bu, sonuna kadar negatif olmayan tam bir çözümü sıralar (varsa).


1
  • Dennis'in önceki fikrimi tersine çeviren sözlerinden sonra, kodu köklerinden değiştirmek zorunda kaldım ve uzun süreli hata ayıklama yaptım ve bana iki kez n ° byte mal oldu: '(.

Matlab (660)

a=input('');b=input('');c=input('');if((min(a*c,b*c)>c*c)&&a*c>0&&b*c>0)||(a*c<0&&b*c<0),-1,return,end,g=abs(gcd(a,b));c=c/g;a=a/g;b=b/g;if(c~=floor(c)),-1,return,end,if(c/a==floor(c/a)&&c/a>0),e=c/a-b;if(e>0),e,a,return,else,c/a,0,return,end,end,if(c/b==floor(c/b)&&c/b>0),e=c/b-a;if(e>0),b,e,return,else,0,c/b,return,end,end,f=max(abs(a),abs(b));if f==abs(a),f=b;b=a;a=f;g=0.5;end,e=(c-b)/a;f=(c-2*b)/a;if(e<0&&f<e),-1,elseif(e<0&&f>e),for(i=abs(c*a):abs((c+1)*a)),e=(c-i*b);if(mod(e,a)==0)if(g==0.5),i,e/a;else,e/a,i,end,return,end,end,else for(i=1:abs(a)),e=(c-i*b);if(e/a<0),-1,elseif(mod(e,a)==0),if(g==0.5),i,e/a,else,e/a,i,end,return,end,end,end,-1
  • Peki, ben onun golf değil biliyorum, çünkü bu tür diller kod uzunluğu azaltma için adapte değildir, ama, zaman karmaşıklığı en iyi olmasını sağlayabilirsiniz.

Açıklama:

  • kod, giriş olarak üç değişmez a, b, c alır, bu son olanlar hesaplamaya devam etmeden önce birkaç koşula tabidir:

    1- (a + b> c) ve (a, b, c> 0) çözelti yoksa!

    2- eğer (a + b <c), (a, b, c <0) çözelti yoksa!

    3- eğer (a, b) ortak zıt işaretlere sahipse c: çözüm yok!

    4- Eğer GCD (a, b) bölünmezse c, yine çözelti olmaz! aksi takdirde tüm varyantları GCD'ye bölün.

  • Bundan sonra, başka bir durumu kontrol etmeliyiz, istenen çözüme giden yolu kolaylaştırmalı ve kısaltmalıdır.

    5- c, a veya b'yi bölerse, çözelti s = (x veya y) = (c- [balta, yb]) / [b, a] = C / [b, a] + [balta, yb] / [b , a] = S + [balta, yb] / [b, a] burada S doğaldır, bu nedenle balta / b veya / a, bundan böyle sırasıyla x = b veya y = a olan negatif olmayan doğrudan çözeltilere sahip olacaktır. (önceki keyfi çözümlerin negatif olması durumunda çözümlerin sadece sıfır değerler olabileceğini unutmayın)

  • program bu aşamaya ulaştığında, düzenli döngülerle tekrarlanan daha büyük sayı aralıklarını süpürmek için, uyum sayesinde, x = (c-yb) / a için daha dar bir çözüm aralığı süpürülür. en büyük arama alanı [xa, x + a] 'dır; burada a bölücüdür.

DENE


euuh, büyük sayılar sorunu, bunu düzeltir (lol ne zaman lol)
Abr001am

Ben hala büyük tamsayılar hakkında düzeltmek için hala küçük bir hata düşünüyorum, hala bu son sonuç yuvarlatılmış olsa da 1152921504606846800.000000 / 576460752303423420.000000 bölme neden alamadım hala.
Abr001am

ohh. Bu hata bug düzeltmek unuttum: p fark ettiğiniz için teşekkürler @Jakube
Abr001am

0

Aksiyom, 460 bayt

w(a,b,x,u)==(a=0=>[b,x];w(b rem a,a,u,x-u*(b quo a)))
d(a,b,k)==(o:List List INT:=[];a=0 and b=0=>(k=0=>[1,1];[]);a=0=>(k=0=>[[1,0]];k rem b=0=>[1,k quo b];[]);b=0=>(k=0=>[[0,1]];k rem a=0=>[k quo a,1];[]);r:=w(a,b,0,1);q:=k quo r.1;(y,x,u,v):=(q*(r.1-r.2*a)quo b,q*r.2,b quo r.1,a quo r.1);m:=min(80,4+abs(k)quo min(abs(a),abs(b)));l:=y quo v;x:=x+l*u;y:=y-l*v;for n in -m..m repeat(t:=x+n*u;z:=y-n*v;t>=0 and z>=0 and t*a+z*b=k=>(o:=cons([t,z],o)));sort(o))

ungolf ve bazı testler

-- input a b and k for equation a*x+b*y=k
-- result one List of List of elments [x,y] of solution of  
-- that equation with x and y NNI (not negative integers) 
-- or Void list [] for no solution
diopanto(a,b,k)==
  o:List List INT:=[]
  a=0 and b=0=>(k=0=>[1,1];[])
  a=0=>(k=0=>[[1,0]];k rem b=0=>[1,k quo b];[])
  b=0=>(k=0=>[[0,1]];k rem a=0=>[k quo a,1];[])
  r:=w(a,b,0,1)
  q:=k quo r.1
  (y,x,u,v):=(q*(r.1-r.2*a)quo b,q*r.2,b quo r.1,a quo r.1)
  m:=min(80,4+abs(k)quo min(abs(a),abs(b)))
  l:=y quo v           -- center the interval
  x:=x+l*u; y:=y-l*v
  for n in -m..m repeat
     t:=x+n*u;z:=y-n*v
     t>=0 and z>=0 and t*a+z*b=k=>(o:=cons([t,z],o))
  sort(o)

 ------------------------------------------------------
(4) -> d(0,-9,0)
   (4)  [[1,0]]
                                                  Type: List List Integer
(5) -> d(2,3,11)
   (5)  [[4,1],[1,3]]
                                                  Type: List List Integer
(6) -> d(2,3,2)
   (6)  [[1,0]]
                                                  Type: List List Integer
(7) -> d(2,3,1)
   (7)  []
                                                  Type: List List Integer
(8) -> d(1152921504606846883,-576460752303423433,1)
   (8)
   [[135637824071393749,271275648142787502],
    [712098576374817182,1424197152749634385],
    [1288559328678240615,2577118657356481268],
    [1865020080981664048,3730040161963328151],
    [2441480833285087481,4882961666570175034]]
                                                  Type: List List Integer

Olası diğer 'çözümlerde' bir hata vardı çünkü sonsuz çözümleri bir Listeye kaydetmeye çalıştı; şimdi maksimum 80 çözüm sınırı getirildi

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.