题目链接
题目描述
给定一个整数 ,需要构造一个长度为
的数组
,该数组被称为“伟大数组”如果满足以下所有条件:
- 数组
是单调非降的(
)。
- 所有元素
都是非负整数。
- 数组的异或和
是
的一个因子(即
)。
如果存在这样的数组,输出任意一个;如果不存在,则输出 -1。
解题思路
这是一个构造性的问题。我们需要找到一种方法来构建一个满足所有三个条件的数组。
最棘手的条件是异或和 必须是
的因子。为了简化这个问题,我们可以尝试构造一个数组,使其异或和
是一个特定的、容易满足整除条件的值。一个绝佳的选择是
,因为
是任何正整数
的因子。
这样,问题就转化为:构造一个长度为 的非降、非负整数数组,使其异或和为
。
我们可以利用异或运算的性质 a \oplus a = 0
来抵消大部分元素,从而精确地控制最终的异或和。我们可以根据 的奇偶性来分情况讨论:
情况一: 是奇数
- 设
。我们可以让数组中大量的元素成对出现以使它们的异或和为 0。
- 我们构造
个(一个偶数)相同的元素。例如,前
个元素都设为
。它们的异或和是
。
- 为了让整个数组的异或和为
,我们只需要让最后一个元素
满足
,所以
。
- 这样构造出的数组为
(包含
个
)。
- 验证条件:
- 非降:
,满足。
- 非负:所有元素都非负,满足。
- 异或和:
,
是
的因子,满足。
- 非降:
- 对于
的特殊情况,此构造给出数组
,异或和为
,
,也满足。
情况二: 是偶数
- 设
。我们不能像奇数情况那样只用一个不同的数,因为
是奇数,无法简单地用相同元素抵消。
- 我们可以让前
个元素(一个偶数)相同来抵消。同样,我们将它们设为
。它们的异或和为
。
- 现在我们需要设置最后两个元素
和
,使得它们的异或和为
(即
),并且满足非降条件 (
)。
- 有很多数对满足异或和为
,例如
等。
- 我们需要找到一对
使得
且
。
- 选择
满足
和
。
- 这样构造出的数组为
(包含
个
)。
- 验证条件:
- 非降:
,满足。
- 非负:所有元素都非负,满足。
- 异或和:
,
是
的因子,满足。
- 非降:
综上所述,我们找到了一种对所有 都有效的构造方法,因此不存在无解的情况。
代码
#include <iostream>
void solve() {
int n;
std::cin >> n;
if (n % 2 != 0) { // n 是奇数
for (int i = 0; i < n - 1; ++i) {
std::cout << "0 ";
}
std::cout << "1\n";
} else { // n 是偶数
for (int i = 0; i < n - 2; ++i) {
std::cout << "0 ";
}
std::cout << "2 3\n";
}
}
int main() {
std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int t = Integer.parseInt(br.readLine());
StringBuilder sb = new StringBuilder();
while (t-- > 0) {
int n = Integer.parseInt(br.readLine());
if (n % 2 != 0) { // n 是奇数
for (int i = 0; i < n - 1; i++) {
sb.append("0 ");
}
sb.append("1\n");
} else { // n 是偶数
for (int i = 0; i < n - 2; i++) {
sb.append("0 ");
}
sb.append("2 3\n");
}
}
System.out.print(sb.toString());
}
}
import sys
def solve():
n_str = sys.stdin.readline()
if not n_str:
return
n = int(n_str)
if n % 2 != 0: # n 是奇数
arr = ["0"] * (n - 1) + ["1"]
else: # n 是偶数
arr = ["0"] * (n - 2) + ["2", "3"]
sys.stdout.write(" ".join(arr) + "\n")
def main():
t_str = sys.stdin.readline()
if not t_str:
return
t = int(t_str)
for _ in range(t):
solve()
if __name__ == "__main__":
main()
算法及复杂度
- 算法:构造法。根据
的奇偶性,我们直接构造并输出一个满足条件的数组,其异或和恒为
。
- 时间复杂度:对于每个测试用例,我们需要循环
次来输出数组元素。由于所有测试用例的
之和有上限,设为
,则总时间复杂度为
。
- 空间复杂度:我们不需要存储整个数组,可以直接在循环中输出,因此只需要常数级别的额外空间,即
。