[CF1523B] Lord of the Values
前言
有意思,但是不难。
题目
题目大意:
\(t\) 组数据,每组数据给一个数组长度 \(n\),以及数组 \(a\)。要求通过以下两个操作使得 \(a\) 数组中的元素变为原来的相反数。
挑选下标 \(1\le i<j\le n.\)
- 将 \(a_i\) 加上 \(a_j\)。
- 将 \(a_j\) 减去 \(a_i\)。
保证 \(n\) 是偶数。操作数不能超过 \(5000\),操作过程中元素的绝对值不能超过 \(10^{18}\)。
\(1\le t\le 10;2\le n\le 10^3;1\le a_i\le 10^9.\)
讲解
解法一(PPL、SY、ZXY、std...)
我们直接考虑两个数的时候怎么搞。
手玩后发现可以采用 \((2,1,1,2,1,1)\) 的操作。
类似的,还有 \((2,1,2,2,1,2),(1,2,1,1,2,1),(1,2,1,2,1,2),(2,1,2,1,2,1),(1,1,2,1,1,2)...\)
每相邻两个数都这么做,次数是 \(3n\)。
浪费可耻。
解法二(XYX)
从后面开始,做操作 \(1\) ,可以使得每个数都变成后缀和,此时花费操作 \(n-1\) 次。
然后从后往前执行操作 \(2\) ,可以使得数组变成 \(Sum,-a_1,-a_2,...,-a_{n-1}\),此时花费操作 \(2n-2\) 次。
然后对 \(1\) 与 偶数位置的数字执行两次操作 \(1\),数组变为: \(\sum_{i=1}^{n}(-1)^ia_i,-a_1,-a_2,...,-a_{n-1}\)。此时花费操作 \(3n-2\) 次。
最后从前往后每相邻的两个数字都执行操作 \(2\) 与操作 \(1\),结束!
总花费 \(5n-4\) 次!
充分利用资源,不愧是标杆。
代码
解法一
/**
* author: tourist
* created: 30.05.2021 17:40:11
**/
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int tt;
cin >> tt;
while (tt--) {
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int foo;
cin >> foo;
}
cout << 3 * n << '\n';
for (int i = 1; i <= n; i += 2) {
cout << "1 " << i << " " << i + 1 << '\n';
cout << "2 " << i << " " << i + 1 << '\n';
cout << "1 " << i << " " << i + 1 << '\n';
cout << "2 " << i << " " << i + 1 << '\n';
cout << "1 " << i << " " << i + 1 << '\n';
cout << "2 " << i << " " << i + 1 << '\n';
}
}
return 0;
}
解法二
#include<set>
#include<queue>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 1005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
LL a[MAXN];
int main() {
int T = read();
while(T --) {
n = read();
for(int i = 1;i <= n;i ++) {
a[i] = read();
}
printf("%d\n",4*(n-1)+n);
for(int i = n;i > 1;i --)
printf("1 %d %d\n",i-1,i);
for(int i = n;i > 1;i --)
printf("2 %d %d\n",i-1,i);
for(int i = 2;i <= n;i += 2) {
printf("1 %d %d\n",1,i);
printf("1 %d %d\n",1,i);
}
for(int i = 1;i < n;i ++) {
printf("2 %d %d\n",i,i+1);
printf("1 %d %d\n",i,i+1);
}
}
return 0;
}