UVA 10090 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
c
2 and n2. Here, c1,
c
2, 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

题意:一个人有n个弹球。如今要把这些弹球所有装进盒子里。第一种盒子每一个盒子c1美元,能够恰好装n1个弹球。另外一种盒子每一个盒子c2元。能够恰好装n2个弹球。找出一种方法把这n个弹球装进盒子,每一个盒子都装满,而且花费最少的钱。

分析:如果第一种盒子买m1个,另外一种盒子买m2个,则n1*m1 + n2*m2 = n。由扩展欧几里得 ax+by=gcd(a,b)= g,如果n%g!=0。则方程无解。

联立两个方程。能够解出m1=nx/g, m2=ny/g,所以通解为m1=nx/g + bk/g, m2=ny/g - ak/g,

又由于m1和m2不能是负数,所以m1>=0, m2>=0,所以k的范围是 -nx/b <= k <= ny/a。且k必须是整数。

如果

k1=ceil(-nx/b)

k2=floor(ny/b)

假设k1>k2的话则k就没有一个可行的解。于是也是无解的情况。

设花费为cost,则cost = c1*m1 + c2*m2,

把m1和m2的表达式代入得

cost=c1*(-xn/g+bk/g)+c2*(yn/g-ak/g) = ((b*c1-a*c2)/g)*k+(c1*x*n+c2*y*n)/g

这是关于k的一次函数。单调性由b*c1-a*c2决定。

若b*c1-a*c2 >= 0,k取最小值(k1)时花费最少;否则,k取最大值(k2)时花费最少。

#include<iostream>
#include<cmath>
using namespace std;
typedef long long LL;

LL extend_gcd(LL a, LL b, LL *x, LL *y)
{
    LL xx, yy, g;
    if(a < b) return extend_gcd(b, a, y, x);
    if(b == 0) {
        *x = 1;
        *y = 0;
        return a;
    }
    else {
        g = extend_gcd(b, a%b, &xx, &yy);
        *x = yy;
        *y = (xx - a/b*yy);
        return g;
    }
}

int main()
{
    LL n, c1, n1, c2, n2, x, y;
    while(cin >> n && n) {
        cin >> c1 >> n1 >> c2 >> n2;
        LL g = extend_gcd(n1, n2, &x, &y);
        if(n % g != 0) {
            cout << "failed" << endl;
            continue;
        }
        LL mink = ceil(-n * x / (double)n2);
        LL maxk = floor(n*y / (double)n1);  // mink <= k <= maxk
        if(mink > maxk) {
            cout << "failed" << endl;
            continue;
        }
        if(c1 * n2 <= c2 * n1) {
            x = n2 / g * maxk + n / g * x;
            y = n / g * y - n1 / g * maxk;
        }
        else {
            x = n2 / g * mink + n / g * x;
            y = n / g * y - n1 / g * mink;
        }
        cout << x << " " << y << endl;
    }
    return 0;
}
时间: 2024-08-24 12:43:32

UVA 10090 Marbles(扩展欧几里得)的相关文章

UVA 10090 - Marbles 拓展欧几里得

I have some (say, n) marbles (small glass balls) and I am going to buy some boxes to store them. Theboxes are of two types:T ype 1: each box costs c1 Taka and can hold exactly n1 marblesT ype 2: each box costs c2 Taka and can hold exactly n2 marblesI

Disgruntled Judge UVA - 12169(扩展欧几里得应用+暴力)

题目给我们的输入数值都是序列中的单数项,我们已知递推公式xi=(aXi-1 + b)mod10001, 所以我们可以将X2表示为X2=(aX1 + b)mod10001,将X3表示为X3=(aX2 + b)mod10001 然后将X2的式子带入到X3中得:X3=(a(aX1 + b)mod10001 + b)mod10001 X3=(a(aX1 + b)+ b)mod10001 X3+10001*k=a*a*X1+a*b+b 10001(-k)+(a+1)b=X3-a*a*X1 --1式 推导出

UVa 12169 (枚举+扩展欧几里得) Disgruntled Judge

题意: 给出四个数T, a, b, x1,按公式生成序列 xi = (a*xi-1 + b) % 10001 (2 ≤ i ≤ 2T) 给出T和奇数项xi,输出偶数项xi 分析: 最简单的办法就是直接枚举a.b,看看与输入是否相符. 1 #include <cstdio> 2 3 const int maxn = 10000 + 5; 4 const int M = 10001; 5 int T, x[maxn]; 6 7 int main() 8 { 9 //freopen("12

uva 10090 - Marbles(欧几里得+通解)

题目链接:uva 10090 - Marbles 题目大意:给出n,表示有n个珠子,现在要用若干个盒子来装.有两种盒子,一种价钱c1,可以装t1个珠子,另一种价钱c2,可以装t2个珠子.要求所卖的盒子刚好装n个珠子,并且价钱最小的方案. 解题思路:用拓展欧几里得算法求出xt1+yt2=n的一对解x′和y′,这样就有通解: x=x′ngcd(t1,t2)+t2gcd(t1,t2)k y=y′ngcd(t1,t2)?t1gcd(t1,t2)k 然后根据性价比选择一种盒子的个数尽量多. #includ

UVa 11768 格点判定(扩展欧几里得求线段整点)

https://vjudge.net/problem/UVA-11768 题意: 给定两个点A(x1,y1)和B(x2,y2),均为0.1的整数倍.统计选段AB穿过多少个整点. 思路: 做了这道题之后对于扩展欧几里得有了全面的了解. 根据两点式公式求出直线 ,那么ax+by=c 中的a.b.c都可以确定下来了. 接下来首先去计算出一组解(x0,y0),因为根据这一组解,你可以写出它的任意解,其中,K取任何整数. 需要注意的是,这个 a' 和 b' 是很重要的,比如说 b' ,它代表的是x每隔 b

UVA 12169 Disgruntled Judge 枚举+扩展欧几里得

题目大意:有3个整数 x[1], a, b 满足递推式x[i]=(a*x[i-1]+b)mod 10001.由这个递推式计算出了长度为2T的数列,现在要求输入x[1],x[3],......x[2T-1], 输出x[2],x[4]......x[2T]. T<=100,0<=x<=10000. 如果有多种可能的输出,任意输出一个结果即可. 由于a和b都小于等于10000,直接枚举a和b暴力可以过.但是有没有更快的方法呢? 首先令递推式的i=2,那么x[2]=(a*x[1]+b)mod 1

UVA 10090 - Marbles (数论)

UVA 10090 - Marbles 题目链接 题意:有两种盒子,一种代价c1,能装n1个珠子,一种代价c2,能装n2个珠子,问如何正好装n个珠子,并且使得代价最少. 思路:利用扩展欧几里得算法求出n1?x+n2?y=n的一个解(x′,y′) 就可以知道x,y的通解分别为 x=x′?n/gcd(n1,n2)+n2/gcd(n1,n2)?t y=y′?n/gac(n1,n2)?n1/gcd(n1,n2)?t 由于x > 0 && y > 0,就可以求出t的范围. 那么t越小x越

【扩展欧几里得】BZOJ1477-青蛙的约会

一直在WA,后来我发现我把东西看反了-- [题目大意] 给出一个长度为L的环状坐标轴,两个点开始时位于(X,0).(Y,0).每次两点分别往右边移动m和n,问能否相遇? [思路] 由题意,可得: X+mt=Y+nt(mod L) (X+mt)-(Y+nt)=L*k (n-m)t+L*k=X-Y. 可以用扩展欧几里得来做.具体来说,显然要满足n-m和L的最大公约数(记为d)要整除X-Y,否则无解.这个可以在扩展欧几里得中求出. 式子可以化简为:[(n-m)/d]*t+(L/d)*k=(X-Y)/d

POJ 1061 青蛙的约会 扩展欧几里得

扩展欧几里得模板套一下就A了,不过要注意刚好整除的时候,代码中有注释 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; typedef long long ll; ll exgcd(ll a, ll b, ll&x, ll&y) { if (b ==