HDU 2669 Romantic 扩展欧几里德---->解不定方程

Romantic

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2385    Accepted Submission(s): 944


Problem Description
The Sky is Sprite.
The Birds is Fly in the Sky.
The Wind is Wonderful.
Blew Throw the Trees
Trees are Shaking, Leaves are Falling.
Lovers Walk passing, and so are You.
................................Write in English class by yifenfei



Girls are clever and bright. In HDU every girl like math. Every girl like to solve math problem!
Now tell you two nonnegative integer a and b. Find the nonnegative integer X and integer Y to satisfy X*a + Y*b = 1. If no such answer print "sorry" instead.
 
Input
The input contains multiple test cases.
Each case two nonnegative integer a,b (0<a, b<=2^31)
 
Output
output nonnegative integer X and integer Y, if there are more answers than the X smaller one will be choosed. If no answer put "sorry" instead.
 
Sample Input
77 51 10 44 34 79
 
Sample Output
2 -3 sorry 7 -3
 
Author
yifenfei
 
Source
 
Recommend
 
扩展欧几里德有很多用处,搜索了一些,大致三种:

(1)求解不定方程;

(2)求解模线性方程(线性同余方程);

(3)求解模的逆元;

 这一道题目是第一种运用.

我们要求的是 (1). ax+by=c  ,满足非负而且最小的x。

1. 要满足(1)有解,那么必须要满足 c%gcd(a,b)==0.为什么呢?

  { 对于gcd(a,b),我们可以知道 a%gcd(a,b)==b%gcd(a,b)==0;最大公约数的知识啊。

  显然  (ax+bx) %gcd(a,b)==0  如果等式成立,左边和右边能够相等,那么c%gcd(a,b)==0.}

 2.先把式子的左边提取出来得到  ax+by,根据欧几里德的知识可以写成  (2). ax+by=gcd(a,b);

   那么就转化成先求 (2).

   在扩展欧几里德的代码中,Ex_GCD(a,b,&x,&y);实际上已经求得了一组解。

   他们分别是回溯得到的x,y; 为了区别,我们把它叫成x0,y0;

   对于ax+by=gcd(a,b)的通解满足

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

   y=y0-a/gcd(a,b)*t;     (t为任意整数)

   这又是怎么得到的呢????

   { 由于ax+by=gcd(a,b) 等价于 a(x+b/gcd(a,b)*t) + b(y-a/gcd(a,b)*t)=gcd(a,b);}

 3.知道了ax+by=gcd(a,b),那么对于ax+by=c,只要在(2)*c/gcd(a,b)。

   原先的x0 转变成 x1=x0*c/gcd(a,b);

                          y1=y0*c/gcd(a,b);

   ax+by=c的通解就可以写成

   x=x1+b/gcd(a,b);

   y=y1 -a/gcd(a,b);

4.要得到最小非负x的值.

   更加x=x1+b/gcd(a,b); 那么满足 x=x%(b/gcd(a,b); while(x<0) x=x+b/gcd(a,b);

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

____________________________________________________________________________

步骤:

赋值k=Ex_GCD(a,b,x,y);也就是k=GCD(a,b);

1.判断 (c%d==0)? No or Yes

2.x=x*c/k;//因为ax+by=c 和 ax+by=gcd(a,b)的转化。

3.b=b/k; //同理

4.b=x%b; while(x<0) x=x+b;

5.根据ax+by=c  ==>   y=  (c-ax)/b;

 1 /*
 2 扩展欧几里德模板题。
 3 
 4 
 5 */
 6 
 7 #include<iostream>
 8 #include<cstdio>
 9 #include<cstdlib>
10 #include<cstring>
11 using namespace std;
12 
13 
14 __int64 Ex_GCD(__int64 a,__int64 b,__int64 &x,__int64 &y)//扩展欧几里得
15 {
16     if(b==0)
17     {
18         x=1;
19         y=0;
20         return a;
21     }
22     __int64 g=Ex_GCD(b,a%b,x,y);
23     __int64 hxl;
24     hxl=x-(a/b)*y;
25     x=y;
26     y=hxl;
27     return g;
28 }
29 
30 int main()
31 {
32     __int64 a,b,k,x,y;
33     while(scanf("%I64d%I64d",&a,&b)>0)
34     {
35         k=Ex_GCD(a,b,x,y);
36         if(k!=1) //因为题目要求 X*a + Y*b = 1
37         {        //所以必须要满足  1 %GCD(a,b) ==0 才有解
38             printf("sorry
");
39             continue;
40         }
41         x=x*1/k;//由于c=1 而且k=1 ,所以没有必要这一步的。
42         //题目要求选择最小非负的x。
43         b=b/k;//这一步也没有必要了
44         x=x%b;
45         if(x<0) x=x+b; //防止x为负数
46         y=(1-a*x)/b; //这个根据 a*x+b*y=1 =>y=(1-a*x)/b;
47         printf("%I64d %I64d
",x,y);
48     }
49     return 0;
50 }
原文地址:https://www.cnblogs.com/tom987690183/p/3251795.html