您的位置:首页 > 其它

PC/UVa 110707/10090

2012-03-09 14:36 204 查看
c1美元的盒子可以装n1个弹珠,c2美元的盒子可以装n2 个弹珠,一共n个弹珠问怎样花最少的钱将盒子装满弹珠,且不留弹珠

一看没思路,再看,可能是跟线性同余方程有关,

欧几里得扩展算法

a*x+b*y=gcd(a,b)

b*x1+(a-floor(a/b)*b)y1=gcd(a,b);

将算式扩展开可得

x=y1;

y=x1-floor(a/b)*y1;

求出 一个x0 y0使得 a*x0+b*y0=gcd(a,b);在这里要说明一点,如果方程 a*x+b*y=n有解,则n|(gcd(a,b));

则 a*x*n/gcd(a,b)+b*y0*n/gcd(a,b)=n;

则 x=x0*n/gcd(a,b) y=y0*n/gcd(a,b); 为方程的一组解

如果方程有解,则又无数解

m1=x+b*t m2=y-a*t;

t 可以任意,如果不知道怎么推出的话,就把它带进去,就知道了

再回到题目中,现在求出方程n1*x+n2*y=n的一组解 x0 y0

x=x0+t*n2 y=y0-t*n1;

又由于题中都为非负数

x>=0 y>=0从而求出t的范围

t1>=(-x0*n/g)/n2//上取整

t2<=(y0*n/g)/n1//下取整

c1*x+c2*y=num+t(c1*n2-c2*n1);

如果c1*n2-c2*n1>0 t=t1

否则 t=t2

到这里基本上就可以求出此题的大部分,但是有一个细节要注意一下//我在这道题上最主要的搞出来了,但是就是范围老是出错,你要小心哦

200

10 20

20 20

200

20 20

10 20

如果这两组数据你能过得话基本上你就可以AC了

代码

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

using namespace std;

long n1,n2,c1,c2;

long n;

long gcd(long a,long b,long &x,long &y)

{

long g,x1,y1;

if(b==0)

{

x=1;

y=0;

return a;

}

if(b>a)

{

g=gcd(b,a,y,x);

}else

{

g=gcd(b,a%b,x1,y1);

x=y1;

y=x1-(a/b)*y1;

}

return g;

}

int main()

{

long t1,t2,x,y,x0,y0,g,t;

while(scanf("%ld",&n)!=EOF)

{

if(n==0) break;

scanf("%ld%ld%ld%ld",&c1,&n1,&c2,&n2);

g=gcd(n1,n2,x0,y0);

t1=ceil((-1.0*x0*n)/n2);

t2=floor((1.0*y0*n)/n1);

if(t1>t2||n%g!=0)

{

printf("failed\n");

continue;

}

if(c1*n2-c2*n1>0)

t=t1;

else

t=t2;

x=x0*n/g+n2*t/g;

y=y0*n/g-n1*t/g;

printf("%ld %ld\n",x,y);

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: