1 条题解
-
0
题解
题目要求统计满足以下条件的有序对 的数量:
- 存在非负整数 使得
直接枚举 或 的范围可达 ,显然不可行。但注意到指数 的增长极快:即使 取最小值 ,当 时 (已超出坐标上限),所以实际有意义的 只有 个。由于 ,最多枚举约 个 。
算法思路(区间求交)
固定 后,条件变为 。我们需要 同时满足:
由第二个式子可得:
$$\left\lceil \frac{l_2}{k^n} \right\rceil \le x \le \left\lfloor \frac{r_2}{k^n} \right\rfloor $$因为 是整数。与第一个区间求交,得到 的有效范围:
$$\max\left(l_1, \left\lceil \frac{l_2}{k^n} \right\rceil\right) \le x \le \min\left(r_1, \left\lfloor \frac{r_2}{k^n} \right\rfloor\right) $$若该区间非空,则其中的每个整数 都对应唯一的 ,从而构成一个合法对。区间内的整数个数为:
$$\max\left(0, \min\left(r_1, \left\lfloor \frac{r_2}{k^n} \right\rfloor\right) - \max\left(l_1, \left\lceil \frac{l_2}{k^n} \right\rceil\right) + 1\right) $$累加所有非负 对应的计数即得答案。
实现细节与避免溢出
标程使用了巧妙的整数运算避免浮点误差和溢出:
-
循环终止条件:
r2/kn >= l1
当 不断增大,直到 时,两个区间的交集一定为空,且更大的 只会使 更小,因此可以提前退出。 -
上取整的无浮点实现: 用整数计算
(l2-1)/kn + 1得到。这是因为当 整除 时,该式恰好等于 ;否则等于 $\lfloor \frac{l_2-1}{k^n} \rfloor + 1 = \lceil \frac{l_2}{k^n} \rceil$。 -
防止溢出:
kn每次乘 可能超出long long范围,但循环条件r2/kn >= l1自然限制了kn不会大到使除法结果小于 ,而 最大 , 最大约 级别,long long完全安全。同时计算区间内整数的公式中使用了0ll和1ll确保long long类型,结果直接加到ans。 -
n=0 的特例:代码中
n=0对应 ,此时条件为 ,只要两个区间有重叠即可统计,公式同样适用。
时间复杂度
每个测试用例枚举 个 ,每次 计算。总测试数 ,最坏计算量约 次操作,轻松通过。
C++ 参考代码(依据标程)
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int tt; cin >> tt; while (tt--) { ll k, l1, r1, l2, r2; cin >> k >> l1 >> r1 >> l2 >> r2; ll kn = 1, ans = 0; for (int n = 0; r2 / kn >= l1; n++) { ans += max(0ll, min(r2 / kn, r1) - max((l2 - 1) / kn + 1, l1) + 1ll); kn *= k; } cout << ans << '\n'; } return 0; }
- 1
信息
- ID
- 6674
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者