CF 966C Big Secret(数论,贪心)
文章目录
题目描述
给定一个长为 $n$ 的数列 $b_i$,要求构造一个长为 $n$ 的数列 $a_i$
$b_1 = a_1$
$b_i = a_i \oplus a_{i - 1}$
要求 $a_i$ 严格单调递增
$1 \le n \le 10^5$
$1 \le b_i \le 2^{60}$
简要做法
$a_i = b_1 \oplus \ldots \oplus b_i$
$a_i = a_{i - 1} \oplus b_i$
要使 $a_i > a_{i - 1}$
则 $b_i$ 的最高位在 $a_{i - 1}$ 中为 $0$
因为 $2^n > 2^1 + 2^2 + \ldots + 2^{n - 2} + 2^{n - 1}$
所以贪心即可
参考代码
#include <stdio.h>
#include <algorithm>
#include <memory.h>
#include <queue>
#define int long long
const int N = 1e5 + 5;
const int M = 60 + 5;
int n, ans[N];
std::queue<int> Q[M];
int read()
{
int x = 0, f = 1;
char ch = getchar();
while ('0' > ch or ch > '9')
f = ch == '-' ? -1 : 1, ch = getchar();
while ('0' <= ch and ch <= '9')
x = x * 10 + ch - 48, ch = getchar();
return x * f;
}
signed main()
{
n = read();
for (int i = 1, x; i <= n; i++)
{
x = read();
for (int j = 60, flag = 1; j >= 0 and flag; j--)
if (x & (1 << j))
Q[j].push(x), flag = 0;
}
for (int i = 1, flag = 1, x = 0; i <= n; i++, flag = 1)
{
for (int j = 0; j <= 60 and flag; j++)
if (!(x & (1LL << j)) and !Q[j].empty())
x ^= (ans[i] = Q[j].front()), Q[j].pop(), flag = 0;
if (flag)
return puts("No"), 0;
}
puts("Yes");
for (int i = 1; i <= n; i++)
printf("%I64d ", ans[i]);
return 0;
}