UVA10090 Marbles【扩展的欧几里得】

Discription
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:
T ype 1: each box costs c1 Taka and can hold exactly n1 marbles
T ype 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 T ypei 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

题意
有n个弹球,现在要把这些弹球全部装进盒子里,第一种盒子每个盒子c1美元,可以恰好装n1个弹球;第二种盒子每个盒子c2元,可以恰好装n2个弹球。找出一种方法把这n个弹球装进盒子,每个盒子都装满,并且花费最少的钱。

思路
这道题,一看样例就很眼熟,其实和坐船过河(我贪心做的)是一道题,然后我拿坐船那道题的代码交过来发现过不了,超时了,然后我就重新看了下,发现这是道扩展的欧几里得题。
参考了题解的分析过程。
参考题解
假设第一种盒子买m1个,第二种盒子买m2个,则n1*m1 + n2*m2 = n
由扩展欧几里得ax+by=gcd(a,b),如果n%gcd(a,b)!=0,则方程无解。特解为:

m2=0时,m1=nx/g;
m1=0时,m2=ny/g;

所以通解为:

m1=nx/g + bk/g;
m2=ny/g - ak/g,

因为m1和m2不能是负数,k的取值范围:-nx/b <= k <= ny/a
将通解带入,花费为:
Money=c1*(-xn/g+bk/g)+c2*(yn/g-ak/g) = ((bc1-ac2)/g)k+(c1xn+c2yn)/g;
所以:
当b
c1-ac2 >= 0,k取最小值时花费最少;
b
c1-a*c2 < 0,k取最大值时花费最少.

AC代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll x,y,n,c1,n1,c2,n2,ans1,ans2;

ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll r=ex_gcd(b,a%b,x,y);
    ll t=x;
    x=y;
    y=t-a/b*y;
    return r;
}

int main()
{
    while(scanf("%lld",&n)!=EOF)
    {
        if(n==0)
            break;
        scanf("%lld%lld%lld%lld",&c1,&n1,&c2,&n2);
        ll tmp=ex_gcd(n1,n2,x,y);
        ll down=ceil(1.0*-n*x/n2);
        ll up=floor(1.0*n*y/n1);
        if(down>up||n%tmp!=0)
        {
            printf("failed\n");
            continue;
        }
        else
        {
            if (c1*n2<c2*n1)
            {
                x=n*x/tmp+n2/tmp*up;
                y=n*y/tmp-n1/tmp*up;
            }
            else
            {
                x=n*x/tmp+n2/tmp*down;
                y=n*y/tmp-n1/tmp*down;
            }
            printf("%lld %lld\n", x, y);
        }
    }
    return 0;
}
发布了335 篇原创文章 · 获赞 110 · 访问量 2万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览