poj 2142 扩展欧几里得

原题实际上就是求方程a*x+b*y=d的一个特解,要求这个特解满足|x|+|y|最小

套模式+一点YY就行了

总结一下这类问题的解法:

对于方程ax+by=c

设tm=gcd(a,b)

先用扩展欧几里得求出方程ax+by=tm的解x0、y0

然后有a*x0+b*y0=tm

令x1=x0*(c/tm),y1=y0*(c/tm)

则a*x1+b*y1=c

x1、y1即原方程的一个特解

这个方程的通解:xi=x1+k*(b/m),yi=y1-k*(a/m)

另:如果要求yi的最小非负解?令r=a/tm,则解y2=(y1%r+r)%r

针对本题,求出x1、y1后可以YY一下:

(1):若x1>0,y1>0,

   1.y1-=(a/m),直到y1<0

   2.y1+=(a/m),直到x1<0

(2):若x1<0,y1>0

     y1-=(a/m),直到y1<0

易知最优解一定出现在这一咕噜里头,操作的同时更新最优答案即可。

 1 #include <iostream>
 2 #include <cmath>
 3 using namespace std;
 4
 5 int gcd(int a,int b){
 6         if (b==0) return a;
 7         return gcd(b,a%b);
 8     }
 9
10 int extgcd(int a,int b,int& x,int& y){
11         int d=a;
12         if (b!=0){
13             d=extgcd(b,a%b,y,x);
14             y-=(a/b)*x;
15         }else{
16             x=1;y=0;
17         }
18         return d;
19     }
20
21 int main()
22 {
23     int a,b,d,ax,ay,ans;
24     while (cin>>a>>b>>d)
25     {
26         if (a==0 && b==0 && d==0)   break;
27         else
28         {
29             int x,y;
30             int tm=extgcd(a,b,x,y);
31             int x1=x*(d/tm),y1=y*(d/tm);
32             int ra=a/tm,rb=b/tm;
33             y1=(y1%ra+ra)%ra;
34             x1=(d-y1*b)/a;
35             int x2=x1,y2=y1;
36             ans=abs(x2)+abs(y2);
37             ax=x2;      ay=y2;
38             if (x2<0)
39             {
40                 while (y2>0)
41                 {
42                     y2-=ra; x2+=rb;
43                     if ((abs(y2)+abs(x2))<ans)
44                     {
45                         ans=abs(y2)+abs(x2);
46                         ax=x2;  ay=y2;
47                     }
48                 }
49             }
50             else if (x2>0)
51             {
52                 while (y2>0)
53                 {
54                     y2-=ra; x2+=rb;
55                     if ((abs(y2)+abs(x2))<ans)
56                     {
57                         ans=abs(y2)+abs(x2);
58                         ax=x2;  ay=y2;
59                     }
60                 }
61                 x2=x1;  y2=y1;
62                 while (x2>0)
63                 {
64                     y2+=ra; x2-=rb;
65                     if ((abs(y2)+abs(x2))<ans)
66                     {
67                         ans=abs(y2)+abs(x2);
68                         ax=x2;  ay=y2;
69                     }
70                 }
71             }
72             cout<<abs(ax)<<" "<<abs(ay)<<endl;
73         }
74     }
75     return 0;
76 }

时间: 2024-10-12 08:00:56

poj 2142 扩展欧几里得的相关文章

The Balance POJ 2142 扩展欧几里得

Description Ms. Iyo Kiffa-Australis has a balance and only two kinds of weights to measure a dose of medicine. For example, to measure 200mg of aspirin using 300mg weights and 700mg weights, she can put one 700mg weight on the side of the medicine an

poj 1061(扩展欧几里得)

青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 90299   Accepted: 16412 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能

POJ 2142 - The Balance [ 扩展欧几里得 ]

题意: 给定 a b n找到满足ax+by=n 的x,y 令|x|+|y|最小(等时令a|x|+b|y|最小) 分析: 算法一定是扩展欧几里得. 最小的时候一定是 x 是最小正值 或者 y 是最小正值 (简单的证明应该是分x,y 符号一正一负,和x,y符号都为正来考虑) 扩欧解的方程为 ax+by = gcd(a, b) 先简化问题,等价为扩欧求的是 a'x+b'y = 1 则原方程等价为 a'x+b'y = n' (a, b, n 全部除以gcd(a, b) ) 先解x为最小正值的时候 x =

POJ 2115 (模线性方程 -&gt; 扩展欧几里得)

题意: for(i=A ; i!=B ;i +=C)循环语句,问在k位操作系统中循环结束次数. 若在有则输出循环次数. 否则输出死循环. 存在这样的情况:i= 65533 :i<=2:i+= 4:时i = 2: 由模线性方程->扩展欧几里得 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> using

POJ 2115 C Looooops(扩展欧几里得应用)

题目地址:POJ 2115 水题..公式很好推.最直接的公式就是a+n*c==b+m*2^k.然后可以变形为模线性方程的样子,就是 n*c+m*2^k==b-a.即求n*c==(b-a)mod(2^k)的最小解.(真搞不懂为什么训练的时候好多人把青蛙的约会都给做出来了,这题却一直做不出来.....这两道不都是推公式然后变形吗.....) 代码如下: #include <iostream> #include <cstdio> #include <string> #incl

扩展欧几里得定理——POJ 1061

对应POJ 题目:点击打开链接 青蛙的约会 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 94409   Accepted: 17470 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得

POJ 1061 青蛙的约会 (扩展欧几里得)

原式 ax + by = c    =>  ax1 + by1 = gcd(a,b); a,b,c为任意整数,d = gcd(a,b),则  ax1 + by1 = d 的一组解是(x1,y1),c是gcd(a,b)的倍数时,其中的一组解为(x1*c/d,y1*c/d);c不是gcd(a,b)的倍数时,无解 青蛙的约会,就是一道例题 按照题意很容易列举出等式:(x+ms) - (y+ns) = k*l;  (k=1.....n)   变形到  扩展欧几里得公式  即可: #include <i

【POJ 1061】青蛙的约会(扩展欧几里得)

[POJ 1061]青蛙的约会(扩展欧几里得) Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 103473   Accepted: 20116 Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它

扩展欧几里得求最小非负整数解 (POJ 1061 青蛙约会为例)

Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的.但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的.为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面. 我们把这