前言
有意思,但是不难。
题目
题目大意:
(t) 组数据,每组数据给一个数组长度 (n),以及数组 (a)。要求通过以下两个操作使得 (a) 数组中的元素变为原来的相反数。
挑选下标 (1le i<jle n.)
- 将 (a_i) 加上 (a_j)。
- 将 (a_j) 减去 (a_i)。
保证 (n) 是偶数。操作数不能超过 (5000),操作过程中元素的绝对值不能超过 (10^{18})。
(1le tle 10;2le nle 10^3;1le a_ile 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 << '
';
for (int i = 1; i <= n; i += 2) {
cout << "1 " << i << " " << i + 1 << '
';
cout << "2 " << i << " " << i + 1 << '
';
cout << "1 " << i << " " << i + 1 << '
';
cout << "2 " << i << " " << i + 1 << '
';
cout << "1 " << i << " " << i + 1 << '
';
cout << "2 " << i << " " << i + 1 << '
';
}
}
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('
')
#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
",4*(n-1)+n);
for(int i = n;i > 1;i --)
printf("1 %d %d
",i-1,i);
for(int i = n;i > 1;i --)
printf("2 %d %d
",i-1,i);
for(int i = 2;i <= n;i += 2) {
printf("1 %d %d
",1,i);
printf("1 %d %d
",1,i);
}
for(int i = 1;i < n;i ++) {
printf("2 %d %d
",i,i+1);
printf("1 %d %d
",i,i+1);
}
}
return 0;
}