题目大意:题目有多个测试样例。每个测试样例第一行为需要乘坐飞机的乘客总数n,第二行为使用一架飞机A的代价costA(简写成ca)和能够容纳的乘客数passengersA(简写成pa),第三行为使用一架飞机B的代价costB(简写成cb)和能够容纳的乘客数passengersB(简写成pb).对每个测试样例求使用飞机A的数量x和飞机B的数量y的值,使得刚好能够容纳n个乘客,并且总代价最小。当存在多组(x, y)满足条件时,选择x最大的一组。当n为0时,输入结束。
解题思路:由题目得 pa * x + pb * y = n。根据裴蜀定理可得,若gcd(pa, pb)能够整除n,则存在整数对(x, y)满足条件(使用扩展欧几里得算法能够求得),反之则不存在解。x *= n / gcd(pa, pb), y *= n / gcd(pa, pb), 能够获得一组解。
通解X = x + pb / gcd(pa, pb) * t, Y = y - pb / gcd(pa, pb) * t.
运用题目条件:
由于X,Y >= 0,所以 (-x) / (pb/gcd(pa, pb)) <= t <= y / (pb/ gcd(pa, pb)).
此时,若确定t的值,即可确定X,Y的解。
根据题目条件:要使总代价最小,首选性价比最高的飞机。
1.若ca * pb <= cb * pa,则飞机A的性价比最高或者两者性价比相同,选择飞机A越多越好,即t越大越好。t取最大值。PS:最大值的下限。
2.若ca * pb > cb * pa, 则飞机B的性价比最高,选择飞机B越多越好,即t越小越好。t取最小值。PS:最小值的上限。
代码如下:
1 #include <cstdio> 2 #include <cmath> 3 4 typedef long long LL; 5 6 template <typename T> 7 T gcdEx(T a, T b, T * x, T *y) { 8 if (b == 0) { 9 *x = 1, *y = 0; 10 return a; 11 } else { 12 T r = gcdEx(b, a % b, x, y); 13 T t = *x; 14 *x = *y; 15 *y = t - a / b * *y; 16 return r; 17 } 18 } 19 template <typename LL > LL gcdEx(LL a, LL b, LL *x, LL *y); 20 21 int main() { 22 LL n, ca, cb, pa, pb; 23 int N = 0; 24 while (++N, scanf("%lld", &n), n) { 25 scanf("%lld%lld%lld%lld", &ca, &pa, &cb, &pb); 26 LL x, y; 27 LL gcd = gcdEx(pa, pb, &x, &y); 28 29 if (n % gcd != 0) { 30 printf("Data set %d: cannot be flown\n", N); 31 } else { 32 x *= n / gcd, y *= n / gcd; 33 34 LL t; 35 if (ca * pb <= cb * pa) 36 t = floor((y + 0.0) / (pa / gcd)); 37 else 38 t = ceil((-x + 0.0) / (pb / gcd)); 39 40 x += pb / gcd * t; 41 y -= pa / gcd * t; 42 printf("Data set %d: %lld aircraft A, %lld aircraft B\n", N, x, y); 43 } 44 } 45 return 0; 46 }
原文:http://www.cnblogs.com/mchcylh/p/5041305.html