Блог пользователя daihan

Автор daihan, 8 лет назад, По-английски

You are given N , A , B find such x and y that (A*x + B*y) = N and x>=0 , y>=0 . It is not guaranteed that N will be always gcd(a,b) .

If such x , y does not exist print -1 , either print x and y in same line separated by space , if there are multiple x , y that satisfy the equation print any of them .

For example: If N=9 , A=2 , B=5

then ans is 2 1 . Because 2*2+5*1=9 . Here A=2 , x=2 and B=5 , y=1 .

Constraint:

1<= N , A , B <= 10^18

INPUT

9 2 5

22 3 7

439365 78717 87873

505383 77277 99291

1000000 3 999997

474441 99291 77277

911106 51038 78188

321361 79845 81826

1000000000000000000 8765433 54343345

OUTPUT

2 1

5 1

0 5

-1

1 1

4 1

1 11

3 1

25359400 18397426840

I have solved using linear loop .

for(long long i=0; i<=n/a; i++)
        if((n-i*a)%b==0) {
            printf("%lld %lld\n",i,(n-i*a)/b);
            return 0;
        }

    printf("-1\n");

But constraint is so big so this would not pass . For this test case n=1000000000000000000 , a=3 , b=798877665 code is getting TLE .

How to solve this problem efficiently ? This is a subproblem of this problem http://mirror.codeforces.com/contest/932/problem/C

UPD solved it using extended euclid here is the code : https://ideone.com/6fzPLF

  • Проголосовать: нравится
  • -15
  • Проголосовать: не нравится

»
8 лет назад, скрыть # |
 
Проголосовать: нравится +28 Проголосовать: не нравится

There is an algorithm named Extended Euclidean algorithm. It runs on logarithmic time.

  • »
    »
    8 лет назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится -14 Проголосовать: не нравится

    But extended euclidian algorithm will work only for A*x+B*y=GCD(A,B) , that means right hand value of above equation must have to be equal to the GCD(A,B) . But i mentioned in the problem that it is not guaranteed that right hand side will be equals to gcd(A,B) .

    In the Above problem A*x+B*y=N , if N!= GCD(A,B) then it is not possible to apply extended euclidian algorithm . How to solve it then ?

  • »
    »
    8 лет назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится 0 Проголосовать: не нравится

    Your idea is not giving correct output . I am not saying you are wrong but why this does not

    if n=9, a=2 , b=5 . Then 2*x+5*y=9

    2*x + 5*y = gcd(2,5)

    =>(2*x*9)/gcd(2,5) + (5*y*9)/gcd(2,5) = gcd(2,5)*9 / gcd(2,5) [ dividing both side with 9/gcd(2,5) ]

    => 2*x*9 + 5*y*9 = 9

    => 18*x + 45*y = 9

    now a=18 , b=45 . Now using extended euclid we get x=-2 , y=1 . Since x and y have to be positive . So i will use the formula

    (x,y) = ( x+t*b/gcd(a,b) , y-k*a/gcd(a,b) ) ;

    x+ t*b/gcd(a,b) >=0 will be true if and only if t>=( -x * gcd(a,b) /b ) ;

    so putting the value ,

    t>=( -x * gcd(a,b) /b )

    t>=( -(-2) * 9/45 )

    t>= 18/45

    y- k*a/gcd(a,b) >=0 will be true if and only if t<=( y*gcd(a,b)/a ) ; putting the value

    t<=( y*gcd(a,b)/a )

    t<= 1* 9/18

    t<= 9/18

    so inequalityes are t>= 18/45 && t<= 9/18 . If i put t=18/45 then it satisfy the inequalities .

    Since (x,y) = ( x+t*b/gcd(a,b) , y-k*a/gcd(a,b) ) ;

    so x= x+t*b/gcd(a,b) ;

    => x= -2+ (18*45)/(9*45)

    => x= -2 + 2

    => x=0

    and y= y-k*a/gcd(a,b)

    => y= 1- (18*18)/(9*45)

    => y= 1-0.8

    => y=0.2

    We finally got x=0 , y=0.2 . But it is not 2*0 + 5 * 0.2 != 9 which does not satisfy a*x + b*y = n

    • »
      »
      »
      8 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Here's the correct step.

      Start with 2x + 5y = 9. Since (2, 5) = 1, we will begin with solving 2x' + 5y' = 1.

      Extended Euclid will give you x' =  - 2 and y' = 1 will work, so taking x = 9x' and y = 9y', we will have x =  - 18 and y = 9. So x =  - 18 + 5t and y =  - 2t + 9 will work.

      To get x, y > 0, we solve the ineq for t and just choose t = 4, giving x = 2 and y = 1.

»
8 лет назад, скрыть # |
 
Проголосовать: нравится +5 Проголосовать: не нравится

But, in that problem N = 1e6 right ?

»
8 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

you can try something like this:

` for(int i=0;i<=n;i++)
    {
        if(a*i<=n&&(n-a*i)%b==0)
        {
            flag=1;
            counta=i;
            countb=(n-a*i)/b;
            break;
        }
    }

`