URL:https://atcoder.jp/contests/abc321
目录
E
Problem/题意
Thought/思路
Code/代码
E
Problem/题意
有一颗 N 个节点的完全二叉树,现在给出节点 X,一个整数 K,问举例节点 X 的长度为 K 的点有多少个?
Thought/思路
来自:https://www.cnblogs.com/Lanly/p/17725350.html
首先考虑以节点 X 为根的子树,求出往下 K 层的左端点和右端点,再与 N 比较大小即可求出这颗子树的答案;
其次考虑与 X 同一个父亲的节点,按照前面求子树的方法求它的答案;
不断往 X 的父节点考虑,求与 X 对称的点的子树答案,直到 X = 1 或者 K == 0,此时若 K == 0,则说明当前的 X 作为单独一个点的答案。
Code/代码
#include "bits/stdc++.h"
#define int long long
__int128 n;
__int128 solve(__int128 x, __int128 k) { // 处理以 x 为根的子树
if (k > 64 or k < 0) return 0;
__int128 len = (1ll << k), l = (x << k);
__int128 r = l + len - 1;
if (l > n) return 0;
if (r > n) {
return n - l + 1;
} else {
return r - l + 1;
}
}
__int128 read() {
__int128 x = 0, f = 1;
char ch = getchar();
while(ch < '0' || ch > '9') {
if(ch == '-') f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9') {
x = x * 10 + ch - '0';
ch = getchar();
}
return x * f;
}
void print(__int128 x) {
if(x < 0) {
putchar('-');
x = -x;
}
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
}
signed main() {
int t; std::cin >> t;
while (t --) {
__int128 x , k;
n = read();x = read();k = read();
int ans = 0;
// 先求 x 的子树
if (k) ans += solve(x, k);
// 不断求 x 的父节点的另一个节点,即另一颗子树
while (x > 1 and k > 0) {
k -= 1; // 往上一层
ans += solve((x ^ 1), k - 1); // 以 x 的父节点的另一个节点为根的子树
x /= 2;
}
// 某个父节点时 k == 0
if (x and k == 0) ans ++;
print(ans);
std::cout << "\n";
}
}