解不定方程ax+by=m的最小解


 

  

  給出方程a*x+b*y=c,其中所有數均是整數,且a,b,c是已知數,求滿足那個等式的x,y值?這個方程可能有解也可能沒解也可能有無窮多個解(注意:這里說的解都是整數解)?

  既然如此,那我們就得找出有解和無解的條件!

  先給出定理:方程a*x+b*y=c有解,當且僅當 c%gcd(a,b)=0。

  定理的證明很容易,如下:

  證明:

  若c%gcd(a,b)=0,則一定存在一個整數K,有c=K*gcd(a,b), 而我們知道a*x+b*y=gcd(a,b)一定存在解(x1, y1)所以就有K*(a*x1 +b*y1 )  = K*gcd(a,b)------>a*K*x1 +b*K*y1 = c,得出解為:(K*x1 , K*y1 )。定理得證。

 

  那么在a*x+b*y=c有解的情況下如何求解呢?

  

  由上可知,a*x+b*y=c a*x+b*y=K*gcd(a,b)是等價的。另外a*x+b*y=gcd(a,b)的一組解為 x1, y1。

  令a1=a/gcd(a,b), b1=b/gcd(a,b),c1=c/gcd(a,b).

  綜上,我們可以得出x,y的一組解就是x1*c1, y1*c1(實際上這個解我們在上面的證明定理的過程中就可以得出這組解,只是我們要的是最小解,所以在此處給出),但是滿足方程的解有無窮多個,在實際的解題中我們常常只要求其最小解。現以求x的最小解為例,至此我們已經求的一組解使得滿足方程a*x+b*y=m,那么a*(x+n*b)+b*(y-n*a)=m顯然也成立。可知x+n*b(n=....-2,-1,0,1,2....)就是方程x解集。存在一個k使得x+k*b>0,x的最小解就是(x+k*b)%b.若我們將方程兩邊同時除以gcd(a,b),則方程變為a1*x+b1*y=c1,同上分析可知。x的最小值就是(x+k*b1)%b1,由於b1<=b,故這個值定會小於等於之前我們認為最小值。在實際求解時常用while(x<0) x+=b來使得為正的條件滿足。

 

  另外給出所有解得公式,若x0,y0是該方程的一組整數解,那么該方程的所有整數解可表示為

  X = x0+b/(a,b)*t;

  Y = y0-a/(a,b)*t;

 代碼如下:

  

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cmath>
 4 using namespace std;
 5 
 6 int Exgcd(int a, int b, int &x, int &y)
 7 {
 8     if(b==0)
 9     {
10         x=1, y=0;
11         return a;
12     }
13     int r = Exgcd(b, a%b, x, y);
14     int tp=x;
15     x = y;
16     y = tp-a/b*y;
17     return r;
18 }
19 
20 void Liner_qu(int a, int b, int c, int d, int &x, int &y)
21 {
22     a /= d, b/= d, c /= d;
23     x *= c; // 任意一解
24     y *= c;
25     int tx = x;
26     x %= b; //最小解,
27     if(x<=0) x += (int)abs(b*1.0); //最小整數解
28     int k=(tx-x)/b;
29     y += k*a; //對應y的最小整數解
30     printf("%d %d\n", x, y);
31 }
32 
33 int main()
34 {
35     int a, b, c, d, x, y;
36     while(~scanf("%d%d%d", &a, &b, &c))
37     {
38         d = Exgcd(a, b, x, y);
39         if(a==0&&b==0&&c==0) puts("1 -1");
40         else if((a==0&&b==0&&c) || c%d || (a&&b==0&&c==0))
41             puts("No solution");
42         else if(a&&b==0)
43             printf("%d %d\n",c/a, -c/a);
44         else if(a==0&&b)
45             printf("1 %d\n",c/b);
46         else
47             Liner_qu(a, b, c, d, x, y);
48     }
49     return 0;
50 }

 

 

參考資料:百度百科

     http://www.cnblogs.com/void/archive/2011/04/18/2020357.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM