P13617 [ICPC 2024 APC] Bit Counting Sequence
对于一个非负整数 \(x\),令 \(p(x)\) 为 \(x\) 的二进制表示中 1 的个数。例如,\(p(26)=3\),因为 \(26=(11010)_2\)。
给定长为 \(n\) 的整数序列 \((a_1, a_2, ..., a_n)\),判断是否存在一个非负整数 \(x\),使得序列 \((p(x), p(x+1), ..., p(x+n-1))\) 与 \((a_1, a_2, ..., a_n)\) 相等。此外,如果存在,你需要计算满足条件的最小的 \(x\)。
假设整个序列里面的最小值 \(\ge 2\),那么我们会发现解 \(x_0\) 的最高位始终没有变过,否则变化的时刻 \(a_t\) 应为 \(1\)。
所以我们可以去掉 \(x_0\) 的最高位然后考虑剩下的子问题。
重复这个过程相当于整体减 \(1\) 直到整个序列的最小值为 \(1\)。
又因为 \(1\) 所在位置必然是 \(2\) 的整数次幂,只有 \(\mathcal O(\log)\) 种取值,暴力 check 即可!
找到子问题的解之后再贪心构造回去就可以啦。
感谢 @wing_heart ,她的思路给了我很大启发!
#include <algorithm>
#include <iostream>
int n, v[500007];
#define p(x) (1ll<<(x))
inline void solve() {
std::cin >> n;
auto check = [](auto&& beg) {
for(int i = 0; i < n; ++i)
if(v[i] != __builtin_popcountll(i + beg))
return 0;
return 1;
};
int min = 100, post = -1;
for(int i = 0; i < n; ++i) {
std::cin >> v[i];
if(v[i] <= min) min = v[i], post = i;
}
if(min == 0) {
std::cout << (check(0) ? "0\n" : "-1\n");
return ;
}
--min;
for(int i = 0; i < n; ++i) v[i] -= min;
for(int i = 0; i <= 60; ++i)
if(p(i) >= post && check(p(i) - post))
return std::cout << (p(i) - post + p(i + min + 1) - p(i + 1)) << "\n", void();
std::cout << "-1\n";
}
int main() {
std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0);
int t; std::cin >> t; for(; t--; ) solve();
}
本文来自博客园,作者:CuteNess,转载请注明原文链接:https://www.cnblogs.com/CuteNess/p/19108101

浙公网安备 33010602011771号