洛谷P6767 [BalticOI 2020/2012 Day0] Roses 题解
题解 P6767 Roses
题目传送门
\(a,c\) 为每束花的朵数,\(b,d\) 为每束花需要的钱
首先简单了解一下题意,大概就是现在给你 \(n\) 朵花,每 \(a\) 朵花 \(b\) 元,每 \(c\) 朵花 \(d\) 元,求最少需要多少钱?
注意:
这里 \(n\) 的范围是 \(\le 10^{15}\) 并且保证数据答案 \(\le 10^{18}\)
所以要开\(\texttt{long long}\)!!!
(犇蒟蒻第一次写的时候就没有注意到,然后喜提 \(\texttt{TLE}\) 。。。)
然后就和你自己花钱去买东西一样,比如你手里有十块钱,这一家超市五块钱可以买两瓶冰红茶,那一家超市10块钱可以买三瓶冰红茶,经过你聪明的大脑计算,就会发现,傻子都知道要去第一家超市
上面这个事情运用到的其实就是性价比,而这道题目也是一样的,用 \(\texttt{double}\) 计算出两种花的性价比
(我看其他题解都用到了 \(\texttt{long double}\) ,其实不需要,因为 \(a,b,c,d\) 的范围都是 \(\le 10^{5}\) ,直接用 \(\texttt{double}\) 就可以了)
以下是计算性价比的代码:
double a1=1.0*b/a;
double a2=1.0*d/c;
//由于a,b,c,d都是正整数,所以在运算前要先乘上一个1.0使其转成浮点数
然后我们可以不妨设a朵b元的方案是性价比高的,实际中假如第二种方案高那就把他们反一下,具体操作如下:
double a1=1.0*/a;
double a2=1.0*d/c;
//由于a,b,c,d都是正整数,所以在运算前要先乘上一个1.0使其转成浮点数
if(a1>a2){
swap(a,c);
swap(b,d);
}
接着我们可以用 \(\texttt{num}\) 存只买第一种方案的数量,但是很明显只买第一种是不对的,所以我们还需要枚举第二种方案
但是关键就是该怎么枚举呢?假如买k组第二种,我们就需要枚举 \(\frac{n}{c}\) 次,显然时间 100% 爆炸,后来经过我的草稿纸一顿嘎嘎乱算,发现,假如
\(k*c \equiv 0 \pmod a\)
就可以只买 \(\frac{k*c}{a}\) 组第一种方案
这样子就只要枚举到 \(\frac{a}{gcd(a,c)}\) 就OK了
这里还要插一点 \(\operatorname{gcd}\) 函数,犇蒟蒻的 \(\operatorname{gcd}\) 写的和网上的不太一样,但是跑起来挺快的,这里给大家展示一下(勿喷):
inline int gcd(int a,int b){
if(b) while((a%=b)&&(b%=a));
return a+b;
}
最后贴上犇蒟蒻的代码
码风很丑,还请见谅
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,a,b,c,d;
inline LL read(){//快读
LL x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
inline int gcd(int a,int b){//最大公约数函数
if(b) while((a%=b)&&(b%=a));
return a+b;
}
LL ans;
int main(){
//freopen("roses.in","r",stdin);
//freopen("roses.out","w",stdout);
n=read();
a=read();b=read();c=read();d=read();
double a1=1.0*b/a;
double a2=1.0*d/c;
if(a1>a2){
swap(a,c);
swap(b,d);
}
LL num1=(n%a==0)?n/a:(n/a+1);
ans=num1*b;
LL num=a/gcd(a,c);
for(LL i=num;i>=0;i--){
LL now=i*d;
if(i*c<=n){
LL k=n-i*c;
LL num2=(k%a==0)?k/a:(k/a+1);
now+=num2*b;
}
ans=min(ans,now);
}
printf("%lld",ans);
return 0;
}
//10001 144 287 125 249
//19929
//一组小数据,供参考