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.