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
1 3
2 4
40
5 9
5 12
0
Sample Output
failed
定理1 gcd(a,b)是ax+by的线性组合的最小正整数,x,y∈z;
定理2 如果ax+by=c,x,y∈z;则c%gcd==0;
定理3 如果a,b是互质的正整数,c是整数,且方程
ax+by=c(1)
有一组整数解x0,y0则此方程的一切整数解可以表示为
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; }