一直被这题狂wrong不止,今天再次看了看别人的解题报告,发现出现了一个重大bug。。
算法思路:1.假设变量N,S1,V1,S2,V22.求S1,S2的最小公倍数LCM
3.求商s=N/LCM,余数y=N%LCM
4.s>=1 则s--,y+=LCM(这个很重要,也是我狂wrong不止的原因。)
5.然后就是枚举,从nsize枚举到0,注意这之前有个很重要的技巧避免超时:枚举s1,s2中拿的量少的
#include <iostream>
#include <cstdio>
#include <algorithm>
//#include <cassert>
using namespace std;
long long ans;
long long N,S1,V1,S2,V2;
long long Choice;
long long gcd(long long x, long long y){
//if (!x || !y) return x > y ? x : y;
for (long long t; t = x % y; x = y, y = t)
;
return y;
}
void input(){
// scanf("%lld%lld%lld%lld%lld",&N,&S1,&V1,&S2,&V2);
cin>>N>>S1>>V1>>S2>>V2;
//assert(N>0 && S1>0 && V1>0 && S2>0 && V2>0 );
}
void solve(){
static long long cnt=1;
ans=0;
if( ( (long long)((long long)(V1*S2)-(long long)(V2*S1)) ) >= 0){
Choice=1;
}
else{
Choice=2;
}
long long G=gcd(S1,S2);
//assert(G>0);
//printf("<<%lld\n",G);
long long gm=(long long)(S1*S2)/G;
//printf("<<%lld\n",gm);
//assert(gm>0);
long long s=N/gm;
long long y=N%gm;
//注意下面这一句,我就是少了这一句,一直wrong
if( s ){
s--;
y+=gm;
}
if( Choice ==1 ){
ans+=s*(long long)((gm/S1)*V1);
}
else{
ans+=s*(long long)((gm/S2)*V2);
}
long long plus=0;
if( S1 < S2 ){
swap(S1,S2),swap(V1,V2);
}
long long nsize=y/S1;
for(long long i=nsize;i>=0 ;--i){
long long temp=y;
long long ts;
temp-=(long long)(S1*i);
//printf("<<%lld\n",temp);
long long nsize2=(long long)(temp/S2);
if( (ts=(long long)((long long)(i*V1) + (long long)(nsize2*V2))) > plus ){
//printf("<<%lld\n",ts);
plus=ts;
}
}
ans+=plus;
// printf("Case #%lld: %lld\n",cnt++,ans);
cout<<"Case #"<<cnt++<<": "<<ans<<endl;
}
int main(){
int T;
cin>>T;
while(T--){
input();
solve();
}
return 0;
}
算法具体证明可参考 yaoz10051538的解题报告