自然に線形なディオファンチン方程式


13

2変数の線形ディオファントス方程式は、ax + by = cの形式の方程式です。ここab、およびcは定数整数であり、xおよびyは整数変数です。

多くの自然に発生するディオファントス方程式では、xyは負の値にできない量を表します。

仕事

係数を受け付けるプログラムまたは機能書き込み、B及びCの入力及び戻りのような任意の一対の自然数(0、1、2、...)のx及びyは式検証すること= cで+ AXを例えば一対場合、存在します。

追加のルール

  • 入力にコードを埋め込まない限り、目的の整数のみを含む入力および出力の任意の形式を選択でき、オプションで言語の配列/リスト/行列/タプル/ベクトル表記を選択できます。

  • 係数abが両方ともゼロではないと仮定できます。

  • コードは、の間の整数のいずれかのトリプレットのために働く必要があり-2 602 60。私のマシン(Intel i7-3770、16 GiB RAM)で1分以内に終了する必要があります。

  • あなたは、このようなMathematicaのようディオファントス方程式を解くため、このタスクを矮小任意のビルトインを、使用することはできませんFindInstanceFrobeniusSolve

  • 時間制限に準拠し、その出力が有効なソリューションと混同されない限り、ソリューションが見つからない場合でも、コードは希望どおりに動作します。

  • 標準の規則が適用されます。

  1. 以下の例は、方程式2x + 3y = 11の有効なI / Oを示しています。これには、正確に2つの有効な解((x、y)=(4,1)および(x、y)=(1,3))があります。

    Input:  2 3 11
    Output: [4 1]
    
    Input:  (11 (2,3))
    Output: [3],(1)
    
  2. 2x + 3y = 2の唯一の有効なソリューションは、ペア(x、y)=(1,0)です。

  3. 以下の例は、式2x + 3y = 1の有効なI / Oを示しています、有効な解はありません

    Input:  (2 3 1)
    Output: []
    
    Input:  1 2 3
    Output: -1
    
    Input:  [[2], [3], [1]]
    Output: (2, -1)
    
  4. (A、B、C)=(1152921504606846883、-576460752303423433、1) 、全ての正しいソリューション(x、y)がその満たす(X、Y)=(135637824071393749 - BN、271275648142787502 +)整数一部非負のためのN


非負整数にもう少し重点を置くのは良いことだと思います。実際、2番目の例には解決策がありません。
Sp3000

intput 1 2 3には有効な出力がありますが... [1、1]
ジャックの弾薬

@JackAmmo:2番目のコードブロックのすべての例は、2x + 3y = 1に対応します。
デニス

ax + bx = kでは、解はx> = 0およびy> = 0でなければならないことを理解しているようです。では、38 * x + 909 * y = 3のx、y> = 0解は誰ですか?
-RosLuP

そのような場合、おそらく存在しないソリューションを返さなければなりません
...-RosLuP

回答:


6

Pyth、92バイト

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

それは非常に怪物です。

オンラインで試してください:デモンストレーション。入力形式はc\n[a,b]で、出力形式は[x,y]です。

整数解が存在しない場合は何も出力せず、自然整数解が存在しない場合は単純にランダムな整数解を出力します。

説明(大まかな概要)

  1. 最初にax + by = gcd(a,b)、拡張ユークリッドアルゴリズムを使用して、方程式の整数解を見つけます。

  2. 次に、解(私の乗算abwith c/gcd(a,b))を変更して、の整数解を取得しax + by = cます。c/gcd(a,b)整数の場合、これは機能します。そうでなければ、解決策は存在しません。

  3. 他のすべての整数解は、for integerの形式a(x+n*b/d) + b(y-n*a/d) = c を持ちます。2つの不等式を使用し、私は6つの可能な値を決定することができます。6つすべてを試して、最も低い係数でソリューションを印刷します。d = gcd(a,b)nx+n*b/d >= 0y-n*a/d >= 0n

説明(詳細)

最初のステップは、方程式の整数解を見つけることax' + by' = gcd(a,b)です。これは、拡張ユークリッドアルゴリズムを使用して実行できます。Wikipediaでどのように機能するかについてのアイデアを得ることができます。唯一の違いは、3列(r_i s_i t_i)を使用する代わりに、6列(r_i-1 r_i s_i-1 s_i t_i-1 t_i)を使用することです。この方法では、最後の2行をメモリに保持する必要はなく、最後の1行のみを保持します。

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. 

今、私は解決策を見つけたいですax + by = c。これはの場合にのみ可能c mod gcd(a,b) == 0です。この式が満たされている場合、単純にと乗算x',y'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]

の整数解がありax + by = cます。xyまたはその両方が負になる場合があることに注意してください。したがって、私たちの目標は、これらを非負に変換することです。

Diophantine方程式の良いところは、1つの初期解のみを使用してすべての解を記述できることです。(x,y)が解である場合、他のすべての解は整数の形式(x-n*b/gcd(a,b),y+n*a/gcd(a,b))ですn

そこで我々は、見つけたいn、どこx-n*b/gcd(a,b) >= 0y+n*a/gcd(a,b >= 0。いくつかの変換後、2つの不等式n >= -x*gcd(a,b)/bとになりn >= y*gcd(a,b)/aます。不等式記号は、潜在的な負aまたはの除算のために他の方向を向く場合があることに注意してくださいb。私はそれについてあまり気にしません、私は単に1つの数が間違いなく-x*gcd(a,b)/b - 1, -x*gcd(a,b)/b, -x*gcd(a,b)/b + 1不等式1をy*gcd(a,b)/a - 1, y*gcd(a,b)/a, y*gcd(a,b)/a + 1満たし、1つの数が不等式2 を満たしていると単純に言いnます。

次に、(x-n*b/gcd(a,b),y+n*a/gcd(a,b))可能な6つの値すべてに対して新しい解を計算しますn。そして、私は最高の最低値でソリューションを印刷します。

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

ソート順によるソートは、次のように機能します。私は例を使用しています2x + 3y = 11

6つのソリューション(これはキーと呼ばれます)をそれぞれソートし、元のソリューションをキーでソートします。

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]

これにより、完全な非負の解が最後にソートされます(ある場合)。


1
  • デニスの発言の後、以前のアイデアが逆さまになったため、コードをそのルートから変更する必要があり、長期のデバッグが必要になり、バイト数が2倍になりました: '(。

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
  • まあ、私はそのタイプの言語はコード長の削減に適合していないので、ゴルフではないことを知っていますが、時間の複雑さを最大限に確保することができます。

説明:

  • コードは入力として3つの不変式a、b、cを取ります。これらの最後の不変式は、計算に進む前にいくつかの条件に抑制されます。

    1-(a + b> c)および(a、b、c> 0)解決策がない場合!

    2- if(a + b <c)、(a、b、c <0)解なし!

    3-(a、b)にcの共通の反対符号がある場合:解なし!

    4- GCD(a、b)がcを分割しない場合、解はありません!、そうでない場合は、すべてのバリアントをGCDで除算します。

  • この後、別の条件をチェックアウトする必要があります。これにより、目的のソリューションへの道が容易になり、短縮されます。

    5- cがaまたはbを除算する場合、解s =(xまたはy)=(c- [ax、yb])/ [b、a] = C / [b、a] + [ax、yb] / [b 、a] = S + [ax、yb] / [b、a]ここで、Sは自然であるため、ax / bまたはby / aはそれぞれx = bまたはy = aである非負の直接解を持ちます。(以前の任意の解がネガティブであることが明らかになった場合、解はゼロ値になる可能性があることに注意してください)

  • プログラムがこの段階に達すると、代わりにx =(c-yb)/ aのより狭い範囲の解がスイープされます。一致のおかげで、より広い範囲の数値をスイープします。最大の検索フィールドは[xa、x + a]で、aは除数です。

それを試してみてください


ええと、多数の問題、それを修正するつもりです(笑)
-Abr001am

大きな整数についてはまだ修正すべきマイナーなバグがあると思うのですが、1152921504606846800.000000 / 576460752303423420.000000の除算が自然数2で出てくる理由はわかりませんが、この最後の結果は丸められます。
-Abr001am

ああ。私はそのバグのバグを修正するのを忘れました:pそれに気づいてくれてありがとう@Jakube
Abr001am

0

公理、460バイト

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))

ウンゴルフといくつかのテスト

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

可能な他の「ソリューション」では、1つのリストに無限のソリューションを保存しようとしたため、バグがありました。今では最大80ソリューションの制限が課されています

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.