您的位置:首页 > 其它

UVA10090->扩展欧几里得

2016-07-28 11:37 204 查看

UVA10090 扩展欧几里得

题意:

现在有两种盒子要装n个珠子,给出每种盒子的容量和价值,求每个盒子恰好能装满的需要花费。

题解:

要求最少花费,就要考虑每种盒子装单个珠子的花费,并且求最优解时让花费较高的那种盒子尽可能少,即先求出这种盒子的最小正整数解。

题目可以等价成一个线性方程求解的问题:

n1*num1 + n2*num2 = n

解法使用扩展欧几里得定理。

只有方程有两个正整数解的时候才有答案。

需要注意的是,即使其中一个未知变量求出来了最小正整数解,另一个有可能为负数。

代码:

#include <stdio.h>
#include <iostream>
#include <cmath>
using namespace std ;
long long extend_gcd(long long a ,long long b ,long long &x ,long long &y)
{
if(a == 0 && b == 0) return -1 ;
if(b == 0)
{
x = 1 ;
y = 0 ;
return a ;
}
long long d = extend_gcd(b , a % b , y , x) ;
y -= a / b * x ;
return d ;
}
int main()
{
long long n , c1 , c2 , n1 , n2 ;
while(cin >> n , n)
{
cin >> c1 >> n1 >> c2 >> n2 ;
long long x0 , y0 ;
long long gcd = extend_gcd(n1 , n2 , x0 , y0) ;
if(n % gcd != 0) printf("failed\n");
else
{
long long num1 , num2 ;
if(c1 * n2 > c2 * n1)
{
num1 = x0 * n / gcd ;
long long r = n2 / gcd ;
num1 = num1 % r ;
if(num1 < 0) num1 += (r>0)?r:-r ;
num2 = (n - num1 * n1) / n2 ;
if(num2<0) {puts("failed");continue;}
}
else
{
num2 = y0 * n / gcd ;
long long r = n1 / gcd ;
num2 = num2 % r ;
if(num2 < 0) num2 += (r>0)?r:-r ;
num1 = (n - num2 * n2) / n1 ;
if(num1<0) {puts("failed");continue;}
}
printf("%lld %lld\n", num1 , num2);
}
}
return 0 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: