126. Boxes time limit per test: 0.5 sec. There are two boxes. There are A balls in the first box, and B balls in the second box (0 < A + B < 2147483648). It is possible to move balls from one box to another. From one box into another one should move as many balls as the other box already contains. You have to determine, whether it is possible to move all balls into one box. Input The first line contains two integers A and B, delimited by space. Output First line should contain the number N - the number of moves which are required to move all balls into one box, or -1 if it is impossible. Sample Input Sample Output 2 6 Sample Output 2 | ||||||
|
我们用(x, y)表示两个盒子里分别有x个球和y个球(不区分是哪个盒子)。假设总共有n个球,经过k步把所有球移到一个盒子里。如果反过来推的话,那么各盒子中球的个数为:
第k步: (0, n);
第k-1步:(n/2, n/2);
第k-2步:(n/4, 3n/4);
第k-3步:(n/8, 7n/8)或(3n/8, 5n/8);
第k-4步:(n/16, 15n/16)或(3n/16, 13n/16)或(5n/16, 11n/16)或(7n/16, 9n/16);
......
这样,我们就发现了规律:除(0, n)这种情况外(一步即可),若(A, B)能化成(x*c, y*c)这种形式,(c为A、B的最大公约数,x和y均为奇数且x+y=2^k,k=1,2,...)则k即为所求的最小步数,输出k;否则,输出-1。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
int gcd(int a, int b)
{
if (!a || !b)
return max(a, b);
int t = a % b;
while (t)
{
a = b;
b = t;
t = a % b;
}
return b;
}
int main()
{
int a, b, ans;
while (scanf("%d %d", &a, &b) != EOF)
{
if (!a || !b)
ans = 0;
else
{
int g = gcd(a, b);
a /= g, b /= g;
if ((a + b) & 1)
ans = -1;
else
{
int t = a + b;
ans = 0;
while (t > 1)
{
if (t % 2 == 0)
{
++ans;
t /= 2;
}
else
{
ans = -1;
break;
}
}
}
}
printf("%d\n", ans);
}
return 0;
}