자연적으로 선형 인 디오 판틴 방정식


13

두 변수 의 선형 디오 판틴 방정식ax + by = c 형식의 방정식입니다. 여기서 a , bc 는 상수 정수이고 xy 는 정수 변수입니다.

많은 자연 발생 디오 판틴 방정식에서 xy 는 음수가 될 수없는 양을 나타냅니다.

직무

계수받는 프로그램이나 함수 작성 , BC 를 입력으로하고 임의의 쌍의 리턴 자연수 (0, 1, 2 것은, ...) , XY 방정식 확인하는 것이 = C로 AX +를 , 예컨대 한 쌍의 경우, 존재합니다.

추가 규칙

  • 입력에 코드를 포함하지 않는 한 원하는 정수만 포함하고 선택적으로 언어의 배열 / 목록 / 매트릭스 / 튜플 / 벡터 표기법과 관련된 입력 및 출력 형식을 선택할 수 있습니다.

  • 계수 ab 가 모두 0이 아닌 것으로 가정 할 수 있습니다 .

  • 코드는 -2 602 60 사이의 정수의 삼중 항에 대해 작동해야합니다 . 내 컴퓨터에서 1 분 안에 완료해야합니다 (Intel i7-3770, 16 GiB RAM).

  • 당신은 매스 매 티카의 같은 디오판토스 방정식을 해결하고, 따라서이 작업을 하찮게 기본 제공 기능, 사용하지 않을 수 있습니다 FindInstance또는 FrobeniusSolve.

  • 그러나 시간 제한을 준수하고 출력을 유효한 솔루션과 혼동 할 수없는 경우 솔루션을 찾을 수없는 경우 코드가 원하는대로 작동 할 수 있습니다.

  • 표준 규칙이 적용됩니다.

  1. 아래 예제는 방정식 2x + 3y = 11에 대한 유효한 I / O를 보여줍니다. 이 솔루션에는 정확히 두 개의 유효한 솔루션 ( (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) = (BN, 271,275,648,142,787,502 + 135,637,824,071,393,749)를 약간 음이 아닌 정수에 대한 N .


음이 아닌 정수를 조금 더 강조하는 것이 좋으며 실제로 두 번째 예에는 해결책이 없다고 생각합니다.
Sp3000

intput 1 2 3은 유효한 출력을 가지고 있지만 ... [1, 1]
Jack Ammo

@JackAmmo : 두 번째 코드 블록의 모든 예제는 2x + 3y = 1에 해당합니다 .
Dennis

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)Extended Euclidean 알고리즘을 사용하여 방정식 에 대한 정수 솔루션을 찾습니다 .

  2. 그럼 난 솔루션 (내 곱셈 수정할 수 있습니다 ab함께을 c/gcd(a,b)의 정수 솔루션을 얻기 위해) ax + by = c. c/gcd(a,b)정수 이면 작동 합니다. 그렇지 않으면 해결책이 없습니다.

  3. 다른 모든 정수 솔루션 형태로 가지고 a(x+n*b/d) + b(y-n*a/d) = cd = gcd(a,b)정수를 n. 두 불평등을 사용 x+n*b/d >= 0하고 y-n*a/d >= 0난 6 개 가능한 값을 확인할 수 있습니다 n. 6 가지를 모두 시도하고 가장 낮은 계수로 솔루션을 인쇄합니다.

설명 (상세)

첫 번째 단계는 방정식에 대한 정수 솔루션을 찾는 것 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) 을 사용한다는 것입니다 . 이렇게하면 마지막 두 행을 메모리에 유지할 필요가 없으며 마지막 행만 유지합니다.

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있습니다. 공지 사항, 즉 x, y또는 둘 모두 음수가 될 수 있습니다. 따라서 우리의 목표는 이것들을 음이 아닌 것으로 바꾸는 것입니다.

Diophantine 방정식의 장점은 하나의 초기 솔루션 만 사용하여 모든 솔루션을 설명 할 수 있다는 것입니다. (x,y)솔루션 인 경우 다른 모든 솔루션은 정수 형식 (x-n*b/gcd(a,b),y+n*a/gcd(a,b))입니다 n.

따라서 우리는 n, where x-n*b/gcd(a,b) >= 0및 을 찾고 싶습니다 y+n*a/gcd(a,b >= 0. 약간의 변형 후에 우리는 두 불평등 n >= -x*gcd(a,b)/b과로 끝납니다 n >= y*gcd(a,b)/a. 부등식 기호는 음수 a또는 로 잠재적 인 나눗셈으로 인해 다른 방향으로 보일 수 있습니다 b. 나는 그것에 대해별로 신경 쓰지 않습니다. 단순히 하나의 수는 -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만족시키고 , 하나의 수는 불평등 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
  • Dennis의 발언 후, 이전 아이디어를 거꾸로 만들었습니다. 근본에서 코드를 변경해야했고 장기 디버깅이 필요했으며 두 번 n 바이트의 바이트가 필요했습니다. '(.

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 인 음이 아닌 직접 솔루션을 갖게된다. (이전의 임의 솔루션이 음수로 표시되는 경우 솔루션은 단지 nil 값일 수 있음에 유의하십시오)

  • 프로그램이이 단계에 도달하면 x = (c-yb) / a에 대한 더 좁은 범위의 솔루션이 합동으로 인해 더 큰 범위의 숫자를 쓸어 넘기 게됩니다. 이는 일정한주기에 의해 반복적으로 발생합니다. 가장 큰 검색 필드는 [xa, x + a]이며 여기서 a는 제수입니다.

시도 해봐


euuh, 많은 수의, 거 수정을 발행하는 (경이 롤)
Abr001am

나는 여전히 큰 정수에 대해 수정하는 사소한 버그를 생각하지만, 왜 1152921504606846800.000000 / 576460752303423420.000000을 나누는 것이 자연수 2로 나오는지 알지 못합니다.이 마지막 결과는 반올림되지만.
Abr001am 2016 년

아. 나는 도청의 버그를 수정하는 것을 잊었다 : 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))

ungolf 및 일부 테스트

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

다른 '솔루션'에서 가능한 한 솔루션을 하나의 목록에 저장하려고 시도했기 때문에 버그가있었습니다. 이제 최대 80 솔루션의 한계가 부과됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.