题解:学而思编程 排位
【题目来源】
学而思编程:排位
【题目描述】
有 \(n\) 个人排成了一队,小X就在其中。
他不知道自己的确切排位,但是他能确定的是,排在他前面的人不少于 \(a\) 个,排在他后面的人不超过 \(b\) 个。
请问,对于他的具体排位,一共有多少种可能性?
【输入】
第一行包含整数 \(T\),表示共有 \(T\) 组数据。
每组数据占一行,包含三个整数 \(n,a,b\)。
【输出】
每组数据输出一行结果,一个整数,表示小X具体排位的可能数量。
【输入样例】
2
3 1 1
5 2 3
【输出样例】
2
3
【核心思想】
-
问题分析:给定 \(n\) 个人排队,小X前面不少于 \(a\) 人,后面不超过 \(b\) 人。求小X排位的可能数量。这是一个区间计数问题,关键在于将"前面不少于 \(a\)"和"后面不超过 \(b\)"转化为小X位置的数学约束,计算合法位置区间的长度。
-
算法选择:
- 位置建模:设小X排在第 \(k\) 位(从 \(1\) 开始计数),前面有 \(k-1\) 人,后面有 \(n-k\) 人
- 不等式约束:将题意转化为关于 \(k\) 的不等式组,求解合法 \(k\) 的区间范围
-
关键步骤:
- 读取输入:读取测试组数 \(T\)
- 逐组处理(循环 \(T\) 次):
- 读取 \(n\)(总人数)、\(a\)(前面不少于 \(a\) 人)、\(b\)(后面不超过 \(b\) 人)
- 建立约束:
- 前面不少于 \(a\) 人:\(k - 1 \ge a \Rightarrow k \ge a + 1\)
- 后面不超过 \(b\) 人:\(n - k \le b \Rightarrow k \ge n - b\)
- 位置合法性:\(1 \le k \le n\)
- 综合约束:\(k \ge \max(a + 1, n - b)\) 且 \(k \le n\)
- 计算合法区间长度:
- 若 \(a + b = n\):合法位置为 \(k \in [a+1, n]\),数量为 \(n - a = b\)
- 若 \(a + b < n\):合法位置为 \(k \in [n-b, n]\),数量为 \(b + 1\)
- 若 \(a + b > n\):约束冲突,前面至少 \(a\) 人且后面最多 \(b\) 人,总人数至少 \(a + 1 + 0 = a + 1\),但 \(a + b > n\) 意味着 \(a > n - b\)。合法位置为 \(k \in [a+1, n]\),数量为 \(n - a\)
- 输出结果:根据上述三种情况输出对应数量
-
时间/空间复杂度:
- 时间复杂度:\(O(T)\),每组数据 \(O(1)\) 计算
- 空间复杂度:\(O(1)\),仅使用常数个变量
-
区间约束的核心思想:
- 双约束交集:小X的位置受"前面不少于 \(a\)"和"后面不超过 \(b\)"两个约束共同限制,合法位置是两者的交集
- 边界情况分析:
- \(a + b = n\):约束恰好饱和,小X位置固定为 \(a+1\) 到 \(n\) 的 \(b\) 个位置
- \(a + b < n\):约束宽松,存在额外空间,小X可以在 \(n-b\) 到 \(n\) 的 \(b+1\) 个位置
- \(a + b > n\):约束过紧,"前面不少于 \(a\)"成为主导限制,合法位置从 \(a+1\) 开始到 \(n\),共 \(n-a\) 个
- 计数技巧:合法位置数量 = 右端点 \(n\) - 左端点 \(\max(a+1, n-b)\) + \(1\),通过分类讨论简化计算
- 适用于区间约束求解、边界条件分析类计数问题
【算法标签】
数学
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int t;
int main()
{
cin >> t;
for (int i = 1; i <= t; i++)
{
int n, a, b;
cin >> n >> a >> b;
// 分三种情况计算
if (a + b == n)
{
cout << b << endl; // 如果刚好坐满,则b的个数就是b
}
if (a + b < n)
{
cout << b + 1 << endl; // 如果还有空位,b可以多坐一个人
}
if (a + b > n)
{
cout << n - a << endl; // 如果座位不够,剩余的座位全给b
}
}
return 0;
}
【运行结果】
2
3 1 1
2
5 2 3
3
浙公网安备 33010602011771号