题解:P12147 【MX-X11-T1】「蓬莱人形 Round 1」仅此而已,就已经足够了
在前言前面
很遗憾,您的题解不符合推荐标准。原因是:非数学公式(一般英文单词、题目名、算法名、人名等)不应使用 LaTeX。
可我寻思着题面就是这么写的啊……
前言(读后续写)
这里是翻译(剪贴板)。(机翻没有美感)
题意简述
定义函数
分析
注意到,函数
- 如果
x 的第k 位为0 ,则f(x) = 2^k 。 - 如果
x 的第k 位为1 ,则f(x) 的取值不仅包括第k 位,还可能包括从第k 位开始向上连续的一段1 (由进位引起)。
为了高效计算
-
第
k 位:每个x 的第k 位在f(x) 中总是1 ,因此贡献为(n+1) \times 2^k 。 -
第
i 位(i > k ):当且仅当x 的第k 位到第i-1 位全为1 时,f(x) 的第i 位为1 。设满足条件的x 的个数为g(i, k, n) ,则第i 位的贡献为g(i, k, n) \times 2^i 。
So,总和
其中
所以我们只需要考虑如何计算
然后分讨一下——对于
Code
#include <bits/stdc++.h>
#define Code using
#define by namespace
#define CleverSea std
typedef long long ll;
Code by CleverSea;
int main() {
int T;
cin >> T;
while (T--) {
ll n, k;
cin >> n >> k;
// 第 k 位的贡献:每个 x 都有贡献
ll ans = (n + 1) * (1LL << k);
// 枚举更高位 i (i > k)
for (int i = k + 1; i <= 60; i++) {
int L = k; // 区间起点
int R = i - 1; // 区间终点
// 计算 M = 2^{R+1} - 2^L,即 [L, R] 位全 1 的数
ll M_val = (1LL << (R + 1)) - (1LL << L);
if (M_val > n) continue; // 无满足条件的 x
ll T_val = n - M_val; // 剩余值
ll W_val = (1LL << (R + 1)); // 模数 W = 2^{R+1}
ll A_max = T_val / W_val; // A 的最大值
ll X_val = (1LL << L) - 1; // 低位最大值 (2^L - 1)
// 计算 A0:满足 T_val - A*W_val >= X_val 的最大 A
ll A0;
if (T_val < X_val) {
A0 = -1;
} else {
A0 = (T_val - X_val) / W_val;
}
// 第一部分:A 从 0 到 min(A0, A_max),每个 A 贡献 2^L 个 B
ll part1 = 0;
ll A1 = min(A0, A_max);
if (A1 >= 0) {
part1 = (A1 + 1) * (1LL << L);
}
// 第二部分:A 从 A0+1 到 A_max,每个 A 贡献 (T_val - A*W_val + 1) 个 B
ll part2 = 0;
ll A_start = A1 + 1;
ll A_end = A_max;
if (A_start <= A_end) {
ll cnt = A_end - A_start + 1; // A 的个数
// 等差数列求和:Σ_{A=A_start}^{A_end} (T_val - A*W_val + 1)
part2 = (T_val + 1) * cnt - W_val * (A_start + A_end) * cnt / 2;
}
ll g = part1 + part2; // 满足条件的 x 的数量
ans += g * (1LL << i); // 第 i 位的贡献
}
cout << ans << '\n';
}
return 0;
}
时间复杂度为