优化用正整数求解ax + by = c的程序

时间:2014-12-20 21:40:47

标签: c optimization equation algebra

我正在编写一个程序,对于任何给定的正整数a< b<如果存在ax + by = c的解,则c将输出YES,其中x和y也是正整数(x,y> 0),或者如果没有解,则输出NO。请记住,我需要处理大数字。

我解决这个问题的方法是从c中减去b,然后检查这个数字是否可以被a除。

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

int main(){
    unsigned long long int a, b, c;
    scanf("%I64u %I64u %I64u", &a, &b, &c);
    while(c>=a+b){ //if c becomes less than a+b, than there's no sollution
        c-=b;
        if(c%a==0){
            printf("YES");
            return 0;
        }
    }
    printf("NO");
    return 0;
}

是否有一种更优化的方法来找到更好的ax + by = c有积极的解决方案?我尝试阅读关于线性丢番图方程,但我找到的只是找到整数解(但不是正数)的方法。

2 个答案:

答案 0 :(得分:2)

到目前为止我的方法。

  1. 使用Euclidean Algorithm查找GCD(a,b)
  2. 当且仅当GCD(a,b)除以c时,才存在ax + by = c的解(整数)。没有整数解决方案意味着没有积极的解决方案。
  3. 使用Extended Euclidean Algorithm解决Diophantine equation,如果提供非正解,则返回NO。
  4. 对于比较,很难找到花费超过一秒钟的例子,但在决定数千个随机方程时,性能差异是显而易见的。 This Lecture有一个解决方案可以找到积极的数量 线性丢番图方程的解。

    typedef unsigned long long int BigInt;
    int pos_solvable(BigInt a, BigInt b, BigInt c) {
      /* returns 1 if there exists x, y > 0 s.t. ax + by = c
       * where 0 < a < b < c
       * returns 0, otherwise
       */
      BigInt gcd = a, bb = b, temp; 
      while (bb) { /* Euclidean Algorithm */
        temp = bb;
        bb = gcd % bb;
        gcd = temp;
      }
      if (c % gcd) { /* no integer (or positive) solution */
        return 0;
      } else { 
        /* Extended Euclidean Algorithm */
        BigInt s = 0, old_s = 1;
        BigInt t = 1, old_t = 0;
        BigInt r = b / gcd, old_r = a / gcd;
    
        while (r > 0) {
          BigInt quotient = old_r / r;
          BigInt ds = quotient * s;
          BigInt dt = quotient * t;
          if (ds > old_s || dt > old_t)
            return 0; /* will give non-positive solution */
    
          temp = s;
          s = old_s - ds;
          old_s = temp;
    
          temp = t;
          t = old_t - dt;
          old_t = temp; 
    
          temp = r;
          r = old_r - quotient * r;
          old_r = temp;
        }
        return 1; 
      }
    }
    

答案 1 :(得分:1)

以下是评论,但对评论部分来说太大了。

这是为了帮助其他人更深入地探讨这个问题。

OP:如果你愿意,可以在你的帖子中加入任何内容。

仍然需要一些具有挑战性的a,b,c

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//#define LLF "%I64u"
#define LLF "%llu"

int main(void) {
  unsigned long long int a, b, c, x, y, sum, c0;
  // scanf(LLF LLF LLF, &a, &b, &c);
  c = c0 = ULLONG_MAX;
  b = 10000223;
  a = 10000169;
  y = 0;
  sum = a + b;
  time_t t0 = time(NULL);
  while (c >= sum) { //if c becomes less than a+b, than there's no solution
    c -= b;
    if (c % a == 0) {
      break;
    }
  }
  if (c % a == 0) {
    y = (c0 - c) / b;
    x = c / a;
    printf("YES " LLF "*" LLF " + " LLF "*" LLF " = " LLF "\n", a, x, b, y, c);
  } else {
    printf("NO\n");
  }
  time_t t1 = time(NULL);
  printf("time :" LLF "\n", (unsigned long long) (t1 - t0));
  return 0;
}

输出

YES 10000169*1844638544065 + 10000223*4688810 = 18446697184563946985
time :0