1 条题解
-
0
好的,这个代码确实是一个可行的构造方法。下面给出详细题解,并附上代码。
题目解析
我们需要构造长度为 的数组,包含 各两次,且每个数字 两次出现的位置之差是 的倍数。
构造思路
给出的代码采用了一种对称的构造方式:
输出:
先输出 (共 个数字)
再输出 (共 个数字)
具体例子
当 时:
- 第一部分:
- 第二部分:
合并得到:
验证:
- 数字 :位置 和 ,距离 ,能被 整除 ✓
- 数字 :位置 和 ,距离 ,能被 整除 ✓
- 数字 :位置 和 ,距离 ,能被 整除 ✓
当 时: 第一部分:
第二部分:
得到:验证:
- :位置 ,距离 ✓
- :位置 ,距离 ✓
- :位置 ,距离 ,能被 整除 ✓
- :位置 ,距离 ,能被 整除 ✓
数学证明
设数组为 。
第一部分:,其中
第二部分:,且对于 ,有即:
对于数字 :
- 如果 :出现在位置 和 ,距离 , 能被 整除 ✓
- 如果 :
- 第一次出现:在位置 (因为第一部分是倒序)
- 第二次出现:在位置 (因为第二部分从 开始是 , 在位置 ?需要仔细验证)
实际上更简单的方法:
对于 :在位置 (第一部分末尾)和 (第二部分第二个),距离 ,能被 整除 ✓
对于 :
第一次出现:位置
第二次出现:位置 (因为 位置是 , 是 , 是 ,..., 位置正好是 )
距离
能被 整除 ✓
特殊情况
- 当 :位置 和 ,距离 ,能被 整除 ✓
- 当 :位置 和 ,距离 ,能被 整除 ✓
因此所有条件满足。
时间复杂度
每个测试用例,总复杂度 ,符合要求。
代码
#include <bits/stdc++.h> using namespace std; int t, n; signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> t; while (t--) { cin >> n; // 输出第一部分: n, n-1, ..., 1 for (int i = n; i >= 1; i--) { cout << i << " "; } // 输出第二部分: n, 1, 2, ..., n-1 cout << n; for (int i = 1; i < n; i++) { cout << " " << i; } cout << "\n"; } }
总结
这个构造巧妙地利用了对称性:
- 第一部分倒序输出 到 ,使得数字 出现在 位置
- 第二部分以 开头,然后顺序输出 到 ,使得 ()出现在 位置
- 距离恰好为 (除 和 外),满足 整除
- 边界情况单独验证也成立
因此该构造正确且简洁。
- 1
信息
- ID
- 7075
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者