【题目链接】
ybt 1973 【16NOIP普及组】买铅笔
洛谷 P1909 [NOIP 2016 普及组] 买铅笔
【题目考点】
1. 简单数学
2. 数组
3. 向上取整
<cmath>中有函数double ceil(double x)
,求x向上取整的值。
如果求正整数 ⌈ a b ⌉ \lceil \frac{a}{b} \rceil ⌈ba⌉也可以使用公式 ⌈ a b ⌉ = ⌊ a − 1 b ⌋ + 1 \lceil \frac{a}{b} \rceil = \lfloor \frac{a-1}{b} \rfloor +1 ⌈ba⌉=⌊ba−1⌋+1,原理见求正整数a和正整数b的商向上取整
【解题思路】
已知需要总笔数为 n n n,只买一种包装,设一种包装的单价为 x x x,笔的数量为 y y y,购买这种笔 m m m包,买到笔的数量为 y ⋅ m y\cdot m y⋅m。
买到笔的数量必须大于等于需要的笔的数量,因此有不等式: y ⋅ m ≥ n y\cdot m \ge n y⋅m≥n,即 m ≥ n y m \ge \frac{n}{y} m≥yn
由于m是整数,所以m的最小值为 ⌈ n y ⌉ \lceil \frac{n}{y} \rceil ⌈yn⌉
购买这种包装的笔的最少花销为 x ⋅ m = x ⌈ n y ⌉ x\cdot m = x\lceil \frac{n}{y} \rceil x⋅m=x⌈yn⌉
⌈ n y ⌉ \lceil \frac{n}{y} \rceil ⌈yn⌉在代码中,可以使用<cmath>中的ceil函数求,写为ceil((double)n/y)
,注意n和y都是int类型变量,要想进行实数除法,需要将其中一个数字转为浮点型量。
或者可以设函数实现公式 ⌈ a b ⌉ = ⌊ a − 1 b ⌋ + 1 \lceil \frac{a}{b} \rceil = \lfloor \frac{a-1}{b} \rfloor +1 ⌈ba⌉=⌊ba−1⌋+1,来求 ⌈ n y ⌉ \lceil \frac{n}{y} \rceil ⌈yn⌉。
比较购买三种包装的笔需要的最小花销,三者中的最小值就是最终结果。
【题解代码】
写法1:实现divCeil函数( ⌈ a b ⌉ = ⌊ a − 1 b ⌋ + 1 \lceil \frac{a}{b} \rceil = \lfloor \frac{a-1}{b} \rfloor +1 ⌈ba⌉=⌊ba−1⌋+1)
#include<bits/stdc++.h>
using namespace std;
int divCeil(int a, int b)//求a/b向上取整(a、b都是正整数)
{return (a-1)/b+1;
}
int main()
{int n, x[3], y[3], ans = 1e9;//ans:最终的最少花费cin >> n;for(int i = 0; i < 3; ++i)cin >> y[i] >> x[i];//x[i]:第i包装的单价 y[i]:第i包装中笔的数量for(int i = 0; i < 3; ++i)if(ans > divCeil(n, y[i])*x[i])ans = divCeil(n, y[i])*x[i];cout << ans << endl;return 0;
}
写法2:使用ceil函数
#include<bits/stdc++.h>
using namespace std;
int main()
{int n, x[3], y[3], ans = 1e9;//ans:最终的最少花费cin >> n;for(int i = 0; i < 3; ++i)cin >> y[i] >> x[i];//x[i]:第i包装的单价 y[i]:第i包装中笔的数量for(int i = 0; i < 3; ++i)ans = min(ans, (int)ceil(double(n)/y[i])*x[i]);//注意:min函数中两个参数类型必须一致 cout << ans << endl;return 0;
}