NYOJ 144 小珂的苦恼

存在整数x和y使得二元一次方程 a*x+b*y=n有解,则n为a,b的最大公约数的整数倍即可,至于为啥,正在研究,应该是数论里的知识。。。。。

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int main()
 4 {
 5     long int a,b,n,a1,b1,t,m,r;
 6     scanf("%ld",&m);
 7     while(m--)
 8     {
 9         scanf("%ld%ld%ld",&a,&b,&n);
10         a1=a;b1=b;
11         if(a1<b1)
12         {t=a1;a1=b1;b1=t;}
13         while(b1)
14         {
15             r=a1%b1;
16             a1=b1;
17             b1=r;
18         }
19         if(n%a1==0)  printf("Yes\n");
20         else printf("No\n");
21     }
22     system("pause");
23     return 0;
24 }

 

知识补充:

1:本题主要用到的是扩展欧几里德定理: 对于与不完全为 0 的非负整数 a,b,gcd(a,b)表示 a,b 的最大公约数那么存在唯一的整数 x,y.使得 gcd(a,b)=ax+by;

先介绍一下:

“扩展欧几里德原理”是由“欧几里德原理”扩展来的,有的书上叫“费蜀(Bezout)定理”,总之有个这个事

c=gcd(a,b)表示a,b两数的最大公约数,则存在:ax+by=c一定存在整数x,y使等式成立

先说一下“欧几里德原理”,其实就是“辗转相除法”,也就是中国老祖先的“更相减损之术”,这个算法的主要目的是求出两个数的最大公约数,具体是一个递归的过程,简单说来是:

gcd(a,b)=gcd(b,a mod b)

终止条件是:gcd(a,b)中的a mod b=0,然后输出b

下面是这个定理的推导过程:

证明“欧几里德原理(算法)”:

设a,b,c为三个不全为零的整数,且有整数t使:a=b*t+c,则a、b与b、c有相同的公约数,因而,gcd(a,b)=gcd(b,c),即gcd(a,b)=gcd(b,a-b*t)(证明这个:d是a,b的公约数,则设a=d*i,b=d*j,由a=b*t+c => c=a-b*t => c=d*(i-j*t),所以,d也是c的公约数)

欧几里德算法(辗转相除法)的工作过程如下:

1、a=b*q[1]+r[1]

2、b=r[1]*q[2]+r[2]

3、r[1]=r[2]*q[3]+r[3]

.

.

.

n、r[n-2]=r[n-1]*q[n]+r[n]

n+1、r[n-1]=r[n]*q[n+1]+r[n+1]

此时,r[n+1]=0,因为每次带余除法,余数至少减一(因为余数比除数小,这里以第一个式子为例,这个式子相当于a除以b商q[1]余r[1],这里一定存在b>r[1]),即b>r[1]>r[2]>r[3]>…>r[n]>r[n+1]=0,而b为有限数,因此必有一个最多不超过b的正整数n存在,使得r[n]>0,而r[n+1]=0,故有

r[n] =gcd(r[n],r[n-1])=…=gcd(r[2],r[1])=gcd(r[1],b)=gcd(a,b)

这就是“欧几里德原理(算法)”的证明,

下面是扩展“欧几里德原理(算法)”的证明:

其实,刚才已经证明了,因为就是辗转相除法的递推过程,然后就是以此把上述递推式迭代累加,化简就不用了,只要写得有些规律,能看出a,b的系数及一些常数项就行了,我得到的是整数倍的a+整数倍的a+整数倍的c=c这个等式,然后再化简可以得到这样的结果c=r[n]=ax+by,此时就证明扩展欧几里德定理了。

有一种特殊情况,就是当gcd(a,b)=1时,存在ax+by=1,x,y存在唯一整数解。

结论(大家都可以记住的):

a*x+b*y=gcd(a,b)x,y一定有整数解,且是唯一的!!

当然如果不好懂得话,可以这样粗略证明:

  • 存在唯一的整数 x,y
  • 使得 gcd(a,b)=ax+by

–      a是gcd的倍数,可设a=i*gcd

–      b是gcd的倍数,可设b=j*gcd

–      现在要用整数个a,b凑出gcd来

–      为了分析方便,不妨设a>b

–      不难看出:a-b可被表示出来,且它也是gcd的倍数

–      因此gcd(a,b)=gcd(b,a-b)=gcd(a,a-b)

–      实际上如果a=n个b+余数,则可以把n个b都减去

–      再怎么减,都是gcd的倍数

–      当n足够大时:a-nb=a mod b

–      因此gcd(a,b)=gcd(b,a mod b)

–      欧几里德定理证明结束

–      从上边证明过程可以看出a-b,a-2b,a-3b,……a-nb都可以被表示出来,且x,y都是整数解

–      当n足够大时:a-nb=a mod b

–      即 a mod b可被表示出来,且x,y为整数解

–      gcd(a,b)=gcd(b,a mod b)等价,且x,y都为整数解

–      相同子问题

–      最终gcd可以被表示出来

这种题考的就是数学知识!!!表示无语!!

 

 

2:x+by=n 其中a,b,n均为整数,要使方程有整数解则:(a,b)|n.  这是一个判断定理,想知道怎么证明的自己查吧,此不再累叙。

这样,本题的主要就是解出a ,b的最大公约数。 解最大公约数的方法我知道的有两种:

        1,辗转相除法       

       2,辗转相减法

下面是具体的代码实现:

       1,辗转相除法:



2,辗转相减法:

  

 两种方法虽然都是可以用来解最大公约数的,可是在时间和空间内存的分配上有很大的差别。。。

 

posted on 2012-08-08 21:04  mycapple  阅读(288)  评论(0编辑  收藏  举报

导航