最开始的想法是找性价比最高的塞满背包,剩余的部分用另一个去填满,后来发现这样的贪心是错的,原因显然
如果要找解的话可能要非常暴力的枚举,显然int32不能暴力
s1*x + s2*y <= N 可转化为 s1*x + s2*y + r = N
显然,N = lcm(s1, s2)时,即 s1*x + s2*y = lcm(s1, s2),哪个性价比高就往背包里塞哪个
就可以把问题转化为 s1*x + s2*y = k*LCM + r (LCM = lcm(s1, s2))
r = N%LCM + m*LCM
k*LCM的部分可以直接塞性价比高的
r的部分比较麻烦,要用最朴素的暴力去做
要让r尽量小,问题的复杂度才会小,最后可证明,r最小为N%LCM + LCM(不会证)
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <queue>
#include <map>
using namespace std;
#define INF 1e9
#define maxn
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define mset(x) memset(x,0,sizeof(x))
typedef __int64 ll;
int kase;
ll N, s1, s2, v1, v2;
ll gcd(ll a, ll b){
if(b==0) return a;
return gcd(b, a%b);
}
ll lcm(ll a, ll b){
return a/gcd(a,b)*b;
}
int main(){
// freopen("a.txt","r",stdin);
// freopen(".out","w",stdout);
cin>>kase;
rep(ks, 1, kase){
cin>>N>>s1>>v1>>s2>>v2;
ll ans=0;
ll LCM = lcm(s1, s2);
ll k = N/LCM, r = N%LCM;
if(k){ k--; r+=LCM; }
if( 1.0*v2/s2 > 1.0*v1/s1 )
ans=LCM/s2*v2*k;
else ans=LCM/s1*v1*k;
ll maxv=0;
if(s2>s1){//令s1>s2
swap(s1, s2);
swap(v1, v2);
}
for(ll x=0; x*s1<=r; x++){
ll tmp = v1*x + (r-x*s1)/s2*v2;
maxv = max(maxv, tmp);
}
ans+=maxv;
printf("Case #%d: %I64d\n", ks, ans);
}
return 0;
}