#P3782. 第1题-卖水果
-
ID: 3126
Tried: 17
Accepted: 14
Difficulty: 3
-
算法标签>数论
第1题-卖水果
解题思路
-
设每个水果被切成固定的
n
块,顾客要求盒内总块数在区间[l, r]
内(含端点)。 -
因为按“个”卖水果,只能买整数个水果
k
,盒内块数为k * n
。 -
问题等价于:是否存在整数
k
使得l ≤ k*n ≤ r
。 这就是整数区间取值问题,可用向上取整/向下取整直接求解:- 可买的最少水果数
k_min = ceil(l / n)
; - 可买的最多水果数
k_max = floor(r / n)
。
- 可买的最少水果数
-
若
k_min > k_max
,说明没有任何整数个数的水果能满足区间要求,输出-1
;否则输出k_min k_max
。
复杂度分析
- 每组数据只做常数次四则运算和取整,时间复杂度
O(1)
。 - 仅使用常数额外变量,空间复杂度
O(1)
。
代码实现
Python
# 功能函数:给定 n, l, r,返回最少与最多水果个数;不可满足返回 None
def solve_case(n, l, r):
# 计算向上取整和向下取整
k_min = (l + n - 1) // n # ceil(l / n)
k_max = r // n # floor(r / n)
if k_min > k_max:
return None
return k_min, k_max
def main():
import sys
data = list(map(int, sys.stdin.read().strip().split()))
if not data:
return
t = data[0]
idx = 1
out_lines = []
for _ in range(t):
n, l, r = data[idx], data[idx + 1], data[idx + 2]
idx += 3
ans = solve_case(n, l, r)
if ans is None:
out_lines.append("-1")
else:
out_lines.append(f"{ans[0]} {ans[1]}")
print("\n".join(out_lines))
if __name__ == "__main__":
main()
Java
import java.util.*;
/**
* ACM 风格主类 Main
*/
public class Main {
// 功能函数:返回 [k_min, k_max];若无解返回 null
static int[] solveCase(int n, int l, int r) {
// 向上取整 l/n = (l + n - 1) / n;向下取整 r/n = r / n
int kMin = (l + n - 1) / n;
int kMax = r / n;
if (kMin > kMax) return null;
return new int[]{kMin, kMax};
}
public static void main(String[] args) {
// 题目数据量很小,使用 Scanner 即可
Scanner sc = new Scanner(System.in);
if (!sc.hasNextInt()) return;
int T = sc.nextInt();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < T; i++) {
int n = sc.nextInt();
int l = sc.nextInt();
int r = sc.nextInt();
int[] res = solveCase(n, l, r);
if (res == null) {
sb.append("-1");
} else {
sb.append(res[0]).append(" ").append(res[1]);
}
if (i + 1 < T) sb.append('\n');
}
System.out.print(sb.toString());
sc.close();
}
}
C++
#include <bits/stdc++.h>
using namespace std;
/*
* 功能函数:给定 n, l, r
* 若可满足,返回 {k_min, k_max};否则返回空可选值
*/
optional<pair<int,int>> solve_case(int n, int l, int r) {
// 计算向上/向下取整
int k_min = (l + n - 1) / n; // ceil(l / n)
int k_max = r / n; // floor(r / n)
if (k_min > k_max) return nullopt;
return make_pair(k_min, k_max);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
if (!(cin >> T)) return 0;
for (int tc = 0; tc < T; ++tc) {
int n, l, r;
cin >> n >> l >> r;
auto ans = solve_case(n, l, r);
if (!ans.has_value()) {
cout << -1;
} else {
cout << ans->first << " " << ans->second;
}
if (tc + 1 < T) cout << "\n";
}
return 0;
}
题目内容
牛牛总是会将一个水果切成 n 块。而顾客购买一盒水果的要求不定,一般来说,会要求盒内总块数大于等于 1 且小于等于 r 。
牛牛只按“个”卖水果,而不是按“块”卖水果,因此:
- 如果没有整数个水果,使得切出的总块数在客户的要求范围内,那么客户就会走开。
现在你需要计算,牛牛的买水果规则能否满足客户的要求,如果满足,则还需要进一步的求出:
- 在满足客户要求的前提下,牛牛最少需要切多少个水果。
- 在满足客户要求的前提下,牛牛最多需要切多少个水果。
输入描述
每个测试文件均包含多组测试数据,第一行输入一个整数 T(1≤T≤1000) 代表数据组数,每组测试数据描述如下:
第一行输入三个整数 n,l,r(1≤n≤100;1≤l≤r≤103) ,表示牛牛能将一个水果切成的固定块数,客户要求的最少块数,最多块数。
输出描述
对于每一组测试数据,新起一行,如果无法满足客户要求,直接输出 −1 ;否则,在一行上输出两个正整数,表示牛牛最少需要切多少个水果、最多要切多少个水果。
样例1
输入
5
2 6 9
3 7 8
1 6 6
9 233 965
10 996 996
输出
3 4
-1
6 6
26 107
-1