目录
题目:
题目描述:
给你n,k,请你构造一个长度为 2n 的序列,使他满足下面的条件:
思路:
当你实际操作起来你会发现这个公式其实不难理解
我们可以规定序列中从头开始连续的(奇数位,偶数位)两两一组(因为长度为 2n 所以总共 n 组),那么这个公式求的就是,前半部分所有组内的差值的绝对值的和 减去 所有组内的差值的和的绝对值
不妨,我们先拿 1 到 2n 的顺序序列试试水,发现在这种情况下,总和等于 0
如果我们对其中一组中两个数进行交换位置呢?会发现总和上升了 2
如果我们把所有的组( n 组 )进行翻转呢?我们会发现.....总和又变回 0 了
如果我们把一半的组( n / 2 组 )进行翻转呢?我们发现总和上升到了 n ,这就对应了公式结果 2k 以及题目中 2k 的取值范围小于等于 n ,这就说明这就是上界。
那么我们可以得出思路,k就代表着我需要翻转的组数,其他组按照正常顺序输出就行。
(不想听我分析的可以直接看代码了)
为什么我们可以这么干?是因为,每当我们进行翻转的时候,前半部分公式的值永远等于 n
而后半部分会随着翻转的组数而改变:
每翻转一个组,会导致差值的变为原来的相反数( 如 -1 变成 1 )这样的变化会导致后半部分的值比原来小 2,从而导致总值多 2
换句话讲,我每翻转一组,都会减少了自身的贡献的同时,还抵消了另一个没有翻转的组的贡献。这也就是为什么对一半的组( n / 2 )的组进行翻转会得到最大值。
思路有了,具体操作请看AC代码
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
std::ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n, k;
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
if (k)
{
cout << 2 * i << ' ' << 2 * i - 1 << ' ';
k--;
}
else
{
cout << 2 * i - 1 << ' ' << 2 * i << ' ';
}
}
return 0;
}