P1292 倒酒

P1292 倒酒
这个题有很多模型,这个是一个变形。
我令一个解为x
两个整数Pa和Pb,分别表示从体积为a ml的酒杯中倒出酒的次数和将酒倒入体积为b ml的酒杯中的次数(酒杯一开始为空)。
b最后是0,所有倒入b中的都会倒入a中,而每次a倒出都是从满的状态倒出来,所以剩下的x=Pb*b-Pa*a。

因为a和b要互质,所以x一定是gcd(a,b)的整数倍,不然令两边同时除以gcd(a,b),左边就是分数了,而右边要求的Pa和Pb包括a,b都是整数,那就无解了。那x最小就是gcd(a,b)。
然后扩欧求出一组解,转而求最小解。

怎么求呢?

如果Pa和Pb是一组解,那么(Pa+a)*b-(Pb+b)*a=x也成立,显然,
(Pa+a/gcd(a,b))*b-(Pb+b/gcd(a,b))*a=x也成立,而且这是可以调整的最小幅度,即不会错过最优解,可以类似的不断调整使解达到最小或变成正数。

 

细节问题
-ax+by=gcd(a,b),这里的变量都是正数,在套扩欧时,还是exgcd(a,b,x,y),然后不断调整使x变成负数,然后输出-x,y即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<queue>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<ctime>
 7 #include<set>
 8 #include<map>
 9 #include<stack>
10 #include<cstring>
11 #define inf 2147483647
12 #define For(i,a,b) for(register int i=a;i<=b;i++)
13 #define p(a) putchar(a)
14 #define g() getchar()
15 //by war
16 //2017.11.6
17 using namespace std;
18 int a,b;
19 int g;
20 int x,y;
21 void in(int &x)
22 {
23     int y=1;
24     char c=g();x=0;
25     while(c<'0'||c>'9')
26     {
27     if(c=='-')
28     y=-1;
29     c=g();
30     }
31     while(c<='9'&&c>='0')x=(x<<1)+(x<<3)+c-'0',c=g();
32     x*=y;
33 }
34 void o(int x)
35 {
36     if(x<0)
37     {
38         p('-');
39         x=-x;
40     }
41     if(x>9)o(x/10);
42     p(x%10+'0');
43 }
44 
45 int exgcd(int a,int b,int &x,int &y)
46 {
47     if(!b)
48     {
49         x=1,y=0;
50         return a;
51     }
52     int t=exgcd(b,a%b,x,y);
53     int temp=x;
54     x=y;
55     y=temp-(a/b)*y;
56     return t;
57 }
58 
59 int main()
60 {
61     in(a),in(b);
62     g=exgcd(a,b,x,y);
63     a/=g;
64     b/=g;
65     while(x>0)
66     {
67         x-=b;
68         y+=a; 
69     }
70     while(x+b<=0&&y>=a)
71     {
72         x+=b;
73         y-=a;
74     }
75     o(g),p('\n');
76     o(-x),p(' '),o(y);
77      return 0;
78 }

 

posted @ 2017-10-20 21:48  WeiAR  阅读(798)  评论(0编辑  收藏  举报