Problem F
Marbles
Input: standard input
Output: standard output
I have some (say, n) marbles (small glass balls) and I am going to buy some boxes to store them. The boxes are of two types:
Type 1: each box costs c1 Taka and can hold exactly n1 marbles
Type 2: each box costs c2 Taka and can hold exactly n2 marbles
I want each of the used boxes to be filled to its capacity and also to minimize the total cost of buying them. Since I find it difficult for me to figure out how to distribute my marbles among the boxes, I seek your help. I want your program to be efficient also.
Input
The input file may contain multiple test cases. Each test case begins with a line containing the integer n (1 <= n <= 2,000,000,000). The second line contains c1 and n1, and the third line contains c2 and n2. Here, c1, c2, n1 and n2 are all positive integers having values smaller than 2,000,000,000.
A test case containing a zero for n in the first line terminates the input.
Output
For each test case in the input print a line containing the minimum cost solution (two nonnegative integers m1 and m2, where mi = number of Type i boxes required) if one exists, print "failed" otherwise.
If a solution exists, you may assume that it is unique.
Sample Input
431 3
2 4
40
5 9
5 12
0
Sample Output
13 1failed
___________________________________________________________________
Rezaul Alam Chowdhury“The easiest way to count cows in a grazing field is to count how many hooves are there and then divide it by four!”
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <algorithm>
#include <cmath>
/****************************************************************************
*
* let d = gcd (n1, n2)
* n1 * x + n2 * y = n <==> n1 / d * x + n2 / d * y = n / d ... (1)
* let n1 / d * x0 + n2 / d * y0 = 1 ... (2)
* x0 and y0 can be get by 'Extended Euclid Algorithm'.
* multiply (2) by 'n / d' and compare to (1), we get:
* x = x0 * n / d
* y = y0 * n / d
* if we have x, y such that:
* n1 * x + n2 * y = n
* then we have:
* n1 * (x + i * n2 / d) + n2 * (y - i * n1 / d) = n (i = 1, 2, ...) ... (3)
* because 'n1 * (x + i * n2 / d)' increase n1 * n2 / d while 'n2 * (y - i * n1 / d)' decrease n1 * n2 / d.
* and here 'x' and 'y' are fixed values.
*
* according to the statement of the problem, x >= 0 and y >= 0.
* so we get:
* x + i * n2 / d >= 0 and y - i * n1 / d >= 0
* solve these two inequations we get the range of 'i', let's note the range [l, u]
*
* the problem asks us to minimize 'c1 * x + c2 * y',
* let z = c1 * (x + i * n2 / d) + c2 * (y - i * n1 / d) ... (4)
* so (4) is what we want to minimize.
* since it's monotonically either increasing or decreasing, what we need to do is examine two cases when i == l and i == u.
*
****************************************************************************/
long long ExEuclid (long long a, long long b, long long &x, long long &y) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
long long d = ExEuclid (b, a % b, y, x);
y -= a / b * x;
return d;
}
long long GCD (long long a, long long b) {
if (b == 0) {
return a;
}
return GCD (b, a % b);
}
int main () {
long long n, c1, n1, c2, n2; // inputs of the problem
while (scanf ("%lld%lld%lld%lld%lld", &n, &c1, &n1, &c2, &n2) == 5 && n) {
long long d = GCD(n1, n2);
if (n % d != 0) {
printf ("failed\n");
continue;
}
long long x0, y0;
ExEuclid (n1 / d, n2 / d, x0, y0);
#ifdef _DEBUG
printf ("d = %lld, n1 / d = %lld, n2 / d = %lld, x0 = %lld, y0 = %lld\n", d, n1 / d, n2 / d, x0, y0);
#endif
/*
* 1) x = n / d * x0 + i * n2 / d, and x >= 0
* 2) y = n / d * y0 - i * n1 / d, and y >= 0
* so, [lower, upper] is the range of 'i'.
*/
long long lower = llrint (ceil (1.0 * -x0 * n / n2)); // lower of 'i'
long long upper = llrint (floor (1.0 * y0 * n / n1)); // upper of 'i'
if (lower > upper) {
printf ("failed\n");
continue;
}
#ifdef _DEBUG
printf ("lower = %lld, upper = %lld\n", lower, upper);
#endif
long long xLower = n / d * x0 + lower * n2 / d;
long long xUpper = n / d * x0 + upper * n2 / d; // by equation 1)
long long yLower = n / d * y0 - lower * n1 / d;
long long yUpper = n / d * y0 - upper * n1 / d; // by equation 2)
long long vLower = c1 * xLower + c2 * yLower; // value of lower
long long vUpper = c1 * xUpper + c2 * yUpper; // value of upper
#ifdef _DEBUG
printf ("xLower = %lld, yLower = %lld, vLower = %lld\n", xLower, yLower, vLower);
printf ("xUpper = %lld, yUpper = %lld, vUpper = %lld\n", xUpper, yUpper, vUpper);
#endif
if (vLower < vUpper) {
#ifdef _DEBUG
printf ("lower\n");
#endif
printf ("%lld %lld\n", xLower, yLower);
} else {
#ifdef _DEBUG
printf ("upper\n");
#endif
printf ("%lld %lld\n", xUpper, yUpper);
}
}
return 0;
}