「NOIP模拟赛」jams倒酒
Jams是一家酒吧的老板,他的酒吧提供2种体积的啤酒,a ml 和 b ml,分别使用容积为a ml 和 b ml的酒杯来装载。
酒吧的生意并不好。Jams发现酒鬼们都很穷,不像他那么土豪。有时,他们会因为负担不起a ml 或者 b ml酒的消费,而不得不离去。因此,Jams决定出手第三种体积的啤酒(较小体积的啤酒)。
Jams只有两种杯子,容积分别为 a ml 和 b ml,而且啤酒杯是没有刻度的。他只能通过两种杯子和酒桶间的互相倾倒来得到新的体积的酒。
倒酒步骤为:
- 规定a>=b
- 酒桶容积无限,酒桶中酒体积无限大。
- 只能包含三种可能的倒酒操作:
- 将酒桶中的酒倒入容积为b ml的酒杯中;
- 将容积为a ml的酒杯中的酒倒入酒桶;
- 将容积为b ml的酒杯中的酒倒入容积为 a ml的酒杯中。
- 每次倒酒必须把杯子倒满或者把被倾倒的杯子倒空。
Jams希望通过若干次倾倒得到容积为 a ml酒杯中剩下的就体积尽可能小,他请求你帮助他设计倾倒方案。
输入:
两个整数a,b(0<b<=a<=10^9)
输出
第一行一个整数,表示可以得到的最小体积的酒。
第二行两个整数Pa和Pb(中间用一个空格分开),分别表示从体积为a ml的酒杯中到处酒的次数和将酒倒入体积为b ml的酒杯的次数。
若有多种可能的Pa,Pb满足要求,那么请输出Pa最小的。若Pa最小的时候有多个Pb,那么输出Pb最小的。
样例输入
5 3
样例输出
1
1 2
倾倒方案为:
- 桶->B;
- B->A;
- 桶->B;
- B->A;
- A->桶;
- B->A;
对于20%的数据,pa,pb总和不超过5
对于60%的数据,pa<=10^8
对于100%的数据,0<b<=a<=10^9
题解
exgcd得出一组解后调整为最优合法解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> #define ll long long using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m; int gcd(int a,int b) { return b==0?a:gcd(b,a%b); } void exgcd(int a,int b,int &x,int &y) { if(b==0){x=1,y=0;return;} exgcd(b,a%b,x,y); int t=x;x=y;y=t-a/b*y; } int main() { n=read();m=read(); int t=gcd(n,m); printf("%d\n",t); int a=n/t,b=m/t; int x,y; exgcd(a,b,x,y); while(x>0||y<0)x-=b,y+=a; while(x+b<=0&&y-a>=0)x+=b,y-=a; printf("%d %d\n",-x,y); return 0; } |
Subscribe