题目描述
前两天,14级计算机巨神真感情学长的一道题被×了!!!被×了!!!被×了!!!
真感情学长灰常的不开心,所以就去找我喝酒,他带了一桶S ml的82年啦飞和两个容量分别为N ml和M ml的杯子,因为他要不醉不归所以带了非常大的两个杯子使得两人一人一杯就可以喝完这一桶酒,也就是说N+M=S,但是陪他喝酒的我不想借此机会暴露出两人酒量高低,所以给他提了一个要求——我们两个人喝的酒必须一样多,这就让真感情很尴尬了,所以他请来他的学弟学妹,也就是你们,帮他解决这个问题,如果谁能解决他就罩着你,以后你就可以在计算机学院横着走了,当然本人为了考验真感情的水平,要求他用最少的操作把这桶酒分成两半(每次操作就是从一个容器向另一个容器倒酒,容器没有刻度),快努力帮助你们的大神学长吧!
输入
多组用例,每组用例占一行包括三个正整数S,N,M分别表示一个桶和两个杯子的容量(N,M<2^31,S=N+M)
以EOF结束输入
输出
对于每组用例,输出一个整数为将该桶酒平分的最少操作数,如果无法平分,那么就输出“ZGQ drinks off !”
样例输入
2 1 1
样例输出
1
测试输入 | 期待的输出 | 时间限制 | 内存限制 | 额外进程 | |
---|---|---|---|---|---|
测试用例 1 | 以文本方式显示
| 以文本方式显示
| 2秒 | 64M | 0 |
测试用例 2 | 以文本方式显示
| 以文本方式显示
| 2秒 | 64M | 0 |
得到通解之后,就是该求答案了。易知肯定一个大于0一个小于0,所以不妨设x>0,y<0,当操作次数最小的时候就是倒入第一个x次,倒入第二个|y|次,但是由于瓶子容积有限,所以倒进倒出操作都是通过大瓶子来解决的,一次倒进操作后为了继续使用小瓶子还要将小瓶子中可乐倒回大瓶子中,倒出操作同理,所以总操作次数是2*(x+y)次,但是要注意最后的(a+b)/2是要放回大瓶子里而不是再倒回,所以乘2之后再减1,所以答案就是2*(|x|+|y|)-1,那么|x|+|y|该怎么求呢?
(截自强神博客)
即答案就是a+b-1.
ps:数据要用long long
AC代码:
#include<stdio.h>
#include<math.h>
long long gcd(long long a, long long b)//求最大公约数
{
long long int c;
while (b != 0) /* 余数不为0,继续相除,直到余数为0 */
{
c = a%b;
a = b;
b = c;
}
return a;
}
int main()
{
long long int s, n, m;
while (scanf("%lld%lld%lld", &s, &n, &m) != EOF)
{
long long int a = n, b = m, c = s / 2;//求ax+by=(a+b)/2
long long int g = gcd(a, b);
if (c%g != 0 || s % 2 == 1)
printf("ZGQ drinks off !\n");
else
{
a = a / g;
b = b / g;
c = c / g;
long long int x = (1 - b) / 2, y = (1 + a) / 2;//此处x和y是两特解,通解为x+k*b,y-k*a
x = x < 0 ? -x : x;
y = y < 0 ? -y : y;
long long int ans = (x+y) * 2;
printf("%lld\n", ans-1);
}
}
return 0;
}