1 条题解
-
0
题目解析
我们有一个整数 ()和一个很大的整数 ()。需要统计满足以下条件的 ()的个数:
- 是 或 的除数
关键观察
观察
由于 且 , 不可能等于 或 (因为异或运算只有当另一个数为 时才可能相等,而 )。
观察
如果 是 的一个除数且 ,那么 。
这意味着除数最多是原数的一半。观察 (核心结论)
如果 ,那么 不可能成为 或 的除数。
证明:
-
首先,当 时, 的最高二进制位一定高于 的最高二进制位。
因此, 的最高位与 相同,所以 $x \oplus y \ge 2^{\lfloor \log_2 y \rfloor} > \frac{y}{2}$。 -
若 是 的除数,则必须满足 (因为除数小于 时最多为 )。
但我们已经得到 ,矛盾。所以 不能是 的除数。 -
同理, 的最高位也高于 的最高位,所以 。
若 是 的除数,则必须满足 (因为除数小于 时最多为 ),但这与 矛盾。
所以 也不能是 的除数。
因此,当 时,不存在满足条件的 。
结论
我们只需要考虑 的范围。
由于 ,,这是一个可以枚举的范围。
算法步骤
对于每个测试用例:
. 读入 和 。 . 令 ,因为:
- 当 时无解
- 同时 不能超过 . 枚举 到 :
- 如果 ,跳过
- 令
- 如果 能整除 或能整除 ,则计数加 . 输出计数
时间复杂度
每个测试用例枚举 个 ,所有测试用例的 之和不超过 ,因此总复杂度为 ,在时限内可行。
代码实现
#include<bits/stdc++.h> using namespace std; using ll = long long; void solve() { int x; ll m; cin >> x >> m; int ans = 0; // 只需要枚举 y < 2x 且 y <= m 的范围 for (int y = 1; y <= min(2LL * x, m); y++) { if (x != y) { int d = x ^ y; if (x % d == 0 || y % d == 0) { ++ans; } } } cout << ans << '\n'; } int32_t main() { ios_base::sync_with_stdio(0); cin.tie(0); int t = 1; cin >> t; while (t--) { solve(); } return 0; }
示例验证
以第一个测试用例 为例:
- ,
- 枚举 到 :
是否能整除 或 有效 否 ❌ 能整除 和 ✅ 能整除 跳过() ❌ 能整除 和 ✅ 否 ❌ 结果: 个有效值(),与题目输出一致。
- 1
信息
- ID
- 6600
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 1
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者