Marbles

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 c1and n1, and the third line contains c2 and n2. Here, c1, c2, n1and n2 are all positive integers having values smaller than 2,000,000,000.

A test case containing a zero forn 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

43
1 3
2 4
40
5 9
5 12
0

Sample Output

13 1
failed
一道扩展欧几里得的题目,和上次那道青蛙约会的很相似,用到几个定理:
定理1 gcd(a,b)是ax+by的线性组合的最小正整数,x,y∈z;
定理2 如果ax+by=c,x,y∈z;则c%gcd==0;
定理3 如果ab是互质的正整数,c是整数,且方程
ax+by=c(1)
有一组整数解x0y0则此方程的一切整数解可以表示为
x=x0+bt;y=y0-at;t∈z;(2)
用这三个定理可以求出第一条方程n1*x+n2*y=n的通解,并求出t在x,y>=0时的取值范围,如果范围不存在即failed,根据t的取值范围,求x*c1+y*c2的最大值,由线性方程的单调性可知,最大值一定在t的边界值产生,代入测试,得出最大值。code见代码
ps:数据比较大必须用64位整形,uva的c++编译器不支持__int64,wa了一次,应写成long long型,关于t的边界值取整问题由于没有想清楚wa了两次,最后采用了cmath函数库的ceil和floor函数,终于才ac了。
#include <iostream>
#include <cmath>
using namespace std;

long long euclid(long long a,long long b){
	if(b==0)
		return a;
	else
		return euclid(b,a%b);
}

long long x,y;

int extended_euclid(long long a,long long b){
	if(b==0){
		x=1;
		y=0;
	}
	else{
		long long temp;
		extended_euclid(b,a%b);
		temp=x-a/b*y;
		x=y;
		y=temp;
	}
	return 0;
}
int main(){
	long long n;
	while(cin>>n&&n!=0){
		long long c1,n1,c2,n2;
		cin>>c1>>n1>>c2>>n2;
		long long gcd;
		gcd=euclid(n1,n2);
		if(n%gcd!=0){
			cout<<"failed"<<endl;
			continue;
		}
		n/=gcd;
		n1/=gcd;
		n2/=gcd;
        extended_euclid(n1,n2);
		x*=n;
		y*=n;
		long long low,up;
		low=(long long)(ceil(1.0*-x/n2));
		up=(long long)(floor(1.0*y/n1));
		if(up<low){
			cout<<"failed"<<endl;
			continue;
		}
		if((x+low*n2)*c1+(y-low*n1)*c2<(x+up*n2)*c1+(y-up*n1)*c2)
			cout<<x+low*n2<<" "<<y-low*n1<<endl;
		else
			cout<<x+up*n2<<" "<<y-up*n1<<endl;
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值