Codeforces Round #750 (Div. 2)的其他题解点我
D. Vupsen, Pupsen and 0
题目大意:
给出一个大小为n的数组a,|ai| ≤ 1e4, n ≤ 1e5
让你构造一个数组b
使得
∑
i
n
a
i
∗
b
i
=
0
且
∑
i
n
∣
b
i
∣
<
=
1
e
9
\sum_i^n a_i * b_i = 0\\且\sum_i^n|b_i| <= 1e9
i∑nai∗bi=0且i∑n∣bi∣<=1e9
思路:
首先我们可以知道两个数ai, aj,我们肯定是可以通过 ai * aj - aj * ai = 0来构造b的,再进行一个优化,我们交换后再除以这两个数的gcd
即
b
i
=
a
i
+
1
a
b
s
(
g
c
d
(
a
i
+
1
,
a
i
)
)
b
i
+
1
=
−
a
i
a
b
s
(
g
c
d
(
a
i
+
1
,
a
i
)
)
b_i = \frac{a_{i+1}}{ abs(gcd(a_{i+1}, a_i))} \\ b_{i +1} =- \frac{a_{i}}{ abs(gcd(a_{i+1}, a_i))}
bi=abs(gcd(ai+1,ai))ai+1bi+1=−abs(gcd(ai+1,ai))ai
那么对于n为奇数的情况呢?
我们可以取最后两个数看成一个数(看成两数的和),来进行操作,
但是得注意一个地方,看成两个数之和的时候可能会出现两数和相加为0的情况
得多进行一次操作
然后还能进行一个优化,因为n为1e5,但是|ai|<=1e4,所以|ai|一定会出现相等的情况,所以我们可以按照绝对值进行排序,这样两个绝对值相等的数会相邻,|bi| = 1
其实不用gcd也是能通过的1e4 *1e5 = 1e9,刚好没问题
AC代码:
#include <bits/stdc++.h>
#define PII pair<int,int>
#define ll long long
using namespace std;
const double eps = 1e-8;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 1<<30;
inline void swap(int &x, int &y){x^=y^=x^=y;}
inline int gcd(int a,int b) {return !b ? a : gcd(b,a%b);}
int b[maxn];
struct a_node{
int x;
int id;
}a[maxn];
bool cmp(a_node x, a_node y){
return abs(x.x) < abs(y.x);
}
int main(){
int T;
scanf("%d", &T);
while(T--){
int n;
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[i].x), b[i] = 0, a[i].id = i;
sort(a + 1, a + n + 1, cmp);
if(n % 2){
for(int i = 1; i < n - 2; i += 2){
int tmp = abs(gcd(a[i].x, a[i + 1].x));
b[a[i].id] = a[i + 1].x/tmp;
b[a[i + 1].id] = (-1) * a[i].x / tmp;
}
int x = a[n - 1].x + a[n].x, y = a[n - 2].x;
int tmp = abs(gcd(x, y));
b[a[n - 2].id] = (-1) * (x) / tmp;
b[a[n].id] = y / tmp, b[a[n - 1].id] = y / tmp;
tmp = abs(gcd(a[n - 2].x, a[n].x));
while(b[a[n - 2].id] == 0){
b[a[n - 2].id] -= a[n].x / tmp;
b[a[n].id] += a[n - 2].x / tmp;
}
}
else {
for(int i = 1; i <= n; i += 2){
int tmp = abs(gcd(a[i].x, a[i + 1].x));
b[a[i].id] = a[i + 1].x/tmp;
b[a[i + 1].id] = -1 * a[i].x / tmp;
}
}
for(int i = 1; i <= n; ++i){
printf("%d ", b[i]);
}
printf("\n");
}
return 0;
}