十分好的不含杂质 Ad-Hoc 构造!难度:8/10,另外几道有难度然后这么好玩的构造题应该是 P12336 第三心脏(比这个题简单一点),P14025 [ICPC 2024 Nanjing R] P ⊕ Q = R(比这个题难一点)。P14158 [ICPC 2022 Nanjing R] 三角形 是史诗级大份,建议别做。
首先容易发现当 2∤n 的时候必然无解,因此只需要考虑 2∣n 的情况即可。
n=2 的情况是简单的,直接对两个数做一次操作就全相等了。而扩展到 n=4 也不难,考虑把四个数分成两组 (A,B) 和 (C,D),对两组的数分别执行一次操作得到 AB,AB,CD,CD,然后此时再交叉配对即 A,C 做一次操作 B,D 做一次操作就可以得到四个 ABCD 满足条件。
同理可以扩展到 n=2k:先将序列分为两个长度为 2n 的序列,对两个序列分别递归处理然后再合并,合并直接把 1,2n+1,2,2n+2,…,2n,n 分别配对处理即可。执行操作的次数是 T(n)=2T(2n)+O(n) 用主定理计算可知操作次数是 O(nlogn) 级别的。
然后再考虑另外一种构造方案:从 n=k−2 来推导出 n=k 时的构造方案。对于给定的 n,先构造 n=2 时的答案,然后考虑一步一步扩展 +2 得到答案。首先把在最后加入的两个数做一次操作让这两个数的值相等,得到形如 a,a,a,…,a,b,b 的序列。然后考虑下面的算法:
- 让前 n−4 个 a 依次和第一个 b 执行操作,得到序列 ab,a2b,a3b,…,an−4b,a,a,an−4b,b。
- 对前 n−4 个数首尾匹配,即第 1 个数和第 n−4 个数做一次操作,第 2 个数和第 n−3 个数做一次操作,以此类推。此时前 n−4 个数的值都变为 an−3b2。
- 对后 4 个数做操作,先让后两个数做一次操作得到两个 an−4b2,然后再让第一个数和第三个数做一次操作,第二个数和第四个数做一次操作。此时这四个数的值都变为 an−3b2。
- 于是此时整个序列的值都相等。
上述算法的执行操作次数是 T(n)=T(n−2)+O(n) 的,简单计算可知有 T(n)=O(n2)。
但是这显然是不好的,考虑优化。每次只在序列末尾加两个数就需要扫一遍整个序列过于浪费。考虑沿用之前 n=2k 时的处理思路,将长度为 n 的序列进行分治:
- 若 4∣n,则直接将序列分为两个长度为 2n 的序列然后按照 n=2k 时的做法直接合并。
- 若 4∤n,则需要将序列分为一个长度为 2n−1 和一个长度为 2n+1 的序列,分别递归处理,然后将第一个序列和第二个序列除最后两个元素以外的部分进行合并,用前面提到的 n=k−2 推导 n=k 的构造方案处理最后剩下的两个元素。
上述算法的执行操作次数是 T(n)=2T(2n)+O(n) 的,主定理计算可知操作次数是 O(nlogn) 级别的。到这里位置都是比较容易的。
但是上述算法仍然无法通过,观察题目信息可知最终需要的操作次数应该是 2n−1 才能通过该题。
思考为什么之前的算法可以以一个比较优的操作次数构造出答案。容易发现,上面的算法构造了一个次数形如等差数列的序列,这样一来只需要两两配对就可以使得其次数均相等。
于是考虑使用类似的思想,执行下面给出的算法:
- 对于一个长度为 n(2∣n)的序列 a1,a2,…,an,考虑将其先两两分组,将 a2k−1 和 a2k 分为一组然后执行一次操作让她们的值相等。此时得到的序列形如 p1,p1,p2,p2,…,pm,pm(m=2n)。
- 对 a1 和 an−2 做一次操作,此时有 a1=an−2=p1pm−1。
- 对 a2 和 an−3 做一次操作,此时有 a2=an−3=p1pm−1。
- 扫一遍所有的奇数位,依次执行操作 (1,n−1),(3,n−1),(5,n−1),…,(n−5,n−1)。
- 执行操作 (2,n−1)。
- 逆序扫一遍所有的偶数位,执行操作 (n−4,n−1),(n−2,n−1),…,(4,n−1)。
- 此时得到的序列形如:
- 对于 a1,a3,a5,…,an−5 的值而言,有:a2i−1=p1pm−1pmj=2∏ipj。
- 对于 a4,a6,a8,…,an−4 的值而言,有:a2i=p12pm−12pm(j=2∏i−1pj)(j=i∏m−2pj2)。
- 特殊的,有 a2=p12pm−12pmj=2∏m−2pj,an−1=p12pm−12pmj=2∏m−2pj2。
- 对于剩下几个位置而言有:an−3=an−2=p1pm−1,an=pm。
- 然后沿用前面直接配对消出的套路,执行下面的操作:
- 对于任意的 i∈[1,m−3]∩N+,都对 (2i−1,2i+2) 执行一次操作。也就是对 a1 和 a4,a3 和 a6,a5 和 a8,……,an−7 和 an−4 执行一次操作。
- 特殊的, 还需要额外对 a2,an−5 执行一次操作(注意上面的操作漏掉了对这两个位置的覆盖)
- 此时得到的序列(记原序列为 a,新得到的序列为 a’)形如:
- a1′=a2′=a3′=…=an−4′=a13a23an−33an−23an−12an2a32a42a52a62…an−52an−42。
- an−3′=an−2′=a1a2an−3an−2。
- an−1′=a12a22an−32an−22an−1ana32a42a52a62…an−52an−42。
- a’n=an−1an。
- 即此时 a’ 序列的前 n−4 项的值均相同,之后倒数第 3,4 项的值也是相同的。
- 最后对后 4 个位置执行操作,对 (n−1,n),(n−3,n−1),(n−2,n) 三组位置执行操作。最终所有位置的值均为 a13a23an−33an−23an−12an2a32a42a52a62…an−52an−42,符合题目的要求。
经过简单计算可知上述算法共执行了 2n−1 次操作,符合题目给出的要求。
注意该算法需要特判 n=2,4,6 时的 corner case。
附:n=12 时上述算法执行的流程(a 序列的变化过程)
(0);(1);(2);(3);(4);(5);(6);(7);(8);(9);(10);(11);(12);(13);(14);(15);(16);(17);(18);(19);(20);(21);(22);(23);(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)(a1a2, a1a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)(a1a2, a1a2, a3a4, a3a4, a5, a6, a7, a8, a9, a10, a11, a12)(a1a2, a1a2, a3a4, a3a4, a5a6, a5a6, a7, a8, a9, a10, a11, a12)(a1a2, a1a2, a3a4, a3a4, a5a6, a5a6, a7a8, a7a8, a9, a10, a11, a12)(a1a2, a1a2, a3a4, a3a4, a5a6, a5a6, a7a8, a7a8, a9a10, a9a10, a11, a12)(a1a2, a1a2, a3a4, a3a4, a5a6, a5a6, a7a8, a7a8, a9a10, a9a10, a11a12, a11a12)(a1a2a9a10, a1a2, a3a4, a3a4, a5a6, a5a6, a7a8, a7a8, a9a10, a1a2a9a10, a11a12, a11a12)(a1a2a9a10, a1a2a9a10, a3a4, a3a4, a5a6, a5a6, a7a8, a7a8, a1a2a9a10, a1a2a9a10, a11a12, a11a12)(a1a2a9a10a11a12, a1a2a9a10, a3a4, a3a4, a5a6, a5a6, a7a8, a7a8, a1a2a9a10, a1a2a9a10, a1a2a9a10a11a12, a11a12)(a1a2a9a10a11a12, a1a2a9a10, a1a2a3a4a9a10a11a12, a3a4, a5a6, a5a6, a7a8, a7a8, a1a2a9a10, a1a2a9a10, a1a2a3a4a9a10a11a12, a11a12)(a1a2a9a10a11a12, a1a2a9a10, a1a2a3a4a9a10a11a12, a3a4, a1a2a3a4a5a6a9a10a11a12, a5a6, a7a8, a7a8, a1a2a9a10, a1a2a9a10, a1a2a3a4a5a6a9a10a11a12, a11a12)(a1a2a9a10a11a12, a1a2a9a10, a1a2a3a4a9a10a11a12, a3a4, a1a2a3a4a5a6a9a10a11a12, a5a6, a1a2a3a4a5a6a7a8a9a10a11a12, a7a8, a1a2a9a10, a1a2a9a10, a1a2a3a4a5a6a7a8a9a10a11a12, a11a12)(a1a2a9a10a11a12, a12a22a3a4a5a6a7a8a92a102a11a12, a1a2a3a4a9a10a11a12, a3a4, a1a2a3a4a5a6a9a10a11a12, a5a6, a1a2a3a4a5a6a7a8a9a10a11a12, a7a8, a1a2a9a10, a1a2a9a10, a12a22a3a4a5a6a7a8a92a102a11a12, a11a12)(a1a2a9a10a11a12, a12a22a3a4a5a6a7a8a92a102a11a12, a1a2a3a4a9a10a11a12, a3a4, a1a2a3a4a5a6a9a10a11a12, a5a6, a1a2a3a4a5a6a7a8a9a10a11a12, a12a22a3a4a5a6a72a82a92a102a11a12, a1a2a9a10, a1a2a9a10, a12a22a3a4a5a6a72a82a92a102a11a12, a11a12)(a1a2a9a10a11a12, a12a22a3a4a5a6a7a8a92a102a11a12, a1a2a3a4a9a10a11a12, a3a4, a1a2a3a4a5a6a9a10a11a12, a12a22a3a4a52a62a72a82a92a102a11a12, a1a2a3a4a5a6a7a8a9a10a11a12, a12a22a3a4a5a6a72a82a92a102a11a12, a1a2a9a10, a1a2a9a10, a12a22a3a4a52a62a72a82a92a102a11a12, a11a12)(a1a2a9a10a11a12, a12a22a3a4a5a6a7a8a92a102a11a12, a1a2a3a4a9a10a11a12, a12a22a32a42a52a62a72a82a92a102a11a12, a1a2a3a4a5a6a9a10a11a12, a12a22a3a4a52a62a72a82a92a102a11a12, a1a2a3a4a5a6a7a8a9a10a11a12, a12a22a3a4a5a6a72a82a92a102a11a12, a1a2a9a10, a1a2a9a10, a12a22a32a42a52a62a72a82a92a102a11a12, a11a12)(a13a23a32a42a52a62a72a82a93a103a112a122, a12a22a3a4a5a6a7a8a92a102a11a12, a1a2a3a4a9a10a11a12, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a3a4a5a6a9a10a11a12, a12a22a3a4a52a62a72a82a92a102a11a12, a1a2a3a4a5a6a7a8a9a10a11a12, a12a22a3a4a5a6a72a82a92a102a11a12, a1a2a9a10, a1a2a9a10, a12a22a32a42a52a62a72a82a92a102a11a12, a11a12)(a13a23a32a42a52a62a72a82a93a103a112a122, a12a22a3a4a5a6a7a8a92a102a11a12, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a3a4a5a6a9a10a11a12, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a3a4a5a6a7a8a9a10a11a12, a12a22a3a4a5a6a72a82a92a102a11a12, a1a2a9a10, a1a2a9a10, a12a22a32a42a52a62a72a82a92a102a11a12, a11a12)(a13a23a32a42a52a62a72a82a93a103a112a122, a12a22a3a4a5a6a7a8a92a102a11a12, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a3a4a5a6a7a8a9a10a11a12, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a9a10, a1a2a9a10, a12a22a32a42a52a62a72a82a92a102a11a12, a11a12)(a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a9a10, a1a2a9a10, a12a22a32a42a52a62a72a82a92a102a11a12, a11a12)(a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a9a10, a1a2a9a10, a12a22a32a42a52a62a72a82a92a102a112a122, a12a22a32a42a52a62a72a82a92a102a112a122)(a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a1a2a9a10, a13a23a32a42a52a62a72a82a93a103a112a122, a12a22a32a42a52a62a72a82a92a102a112a122)(a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122, a13a23a32a42a52a62a72a82a93a103a112a122)
namespace Loyalty
{
int a[N];
inline void init() {}
inline void main([[maybe_unused]] int _ca, [[maybe_unused]] int _atc)
{
int n;
cin >> n;
if (n & 1)
cout << 0 << '\n';
else if (n == 2)
cout << 1 << '\n' << 1 << '\n' << 1 << ' ' << 2 << '\n';
else if (n == 4)
{
cout << 1 << '\n';
cout << 4 << '\n';
cout << 1 << ' ' << 2 << '\n';
cout << 3 << ' ' << 4 << '\n';
cout << 1 << ' ' << 3 << '\n';
cout << 2 << ' ' << 4 << '\n';
}
else if (n == 6)
{
cout << 1 << '\n';
cout << 11 << '\n';
cout << 1 << ' ' << 2 << '\n'; // 1
cout << 3 << ' ' << 4 << '\n'; // 2
cout << 1 << ' ' << 3 << '\n'; // 3
cout << 2 << ' ' << 4 << '\n'; // 4
cout << 5 << ' ' << 6 << '\n'; // 5
cout << 1 << ' ' << 5 << '\n'; // 6
cout << 2 << ' ' << 5 << '\n'; // 7
cout << 1 << ' ' << 2 << '\n'; // 8
cout << 5 << ' ' << 6 << '\n'; // 9
cout << 3 << ' ' << 5 << '\n'; // 10
cout << 4 << ' ' << 6 << '\n'; // 11
}
else
{
cout << 1 << '\n';
vector<pair<int, int>> op;
for (int i = 1; i <= n; i += 2)
op.emplace_back(i, i + 1);
op.emplace_back(1, n - 2);
op.emplace_back(2, n - 3);
for (int i = 1; i <= n - 5; i += 2)
op.emplace_back(i, n - 1);
op.emplace_back(2, n - 1);
for (int i = n - 4; i >= 4; i -= 2)
op.emplace_back(i, n - 1);
for (int i = 1; i <= n / 2 - 3; ++i)
op.emplace_back(2 * i - 1, 2 * i + 2);
op.emplace_back(2, n - 5);
op.emplace_back(n - 1, n);
op.emplace_back(n - 3, n - 1);
op.emplace_back(n - 2, n);
cout << op.size() << '\n';
for (auto &[x, y] : op)
cout << x << ' ' << y << '\n';
}
}
}
喜欢的话,留下你的评论吧~