题解:AT_abc413_d [ABC413D] Make Geometric Sequence
一个有趣的题。
我们先考虑一个所有数的符号相同的数列如何判断。我们将其从小到大排序后,如果是一个等比数列,那么则会有:
于是有,
于是我们排序后直接遍历判断即可。
现在我们考虑正负数。显然,如果
对于一个公比为正数的等比数列,如果我们将公比取相反数,我们会发现最后的结果只是将原数列的偶数项取了相反数,如果要让奇数项取相反数只需要让首项取反即可。
于是我们将
但是我们考虑下面一种情况:
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <numeric>
long long g[200005];
int main() {
int T;
for (scanf("%d", &T); T--;) {
int n, fsnum = 0, zsnum = 0; //fsnum->负数的数量,zsnum->正数的数量
scanf("%d", &n);
for (int i = 0; i < n; ++i) scanf("%lld", g + i);
bool ok = 1;
for (int i = 0; i < n; ++i) {
if (g[i] > 0) ++zsnum;
else ++fsnum;
if (abs(g[i]) != abs(g[0])) { //判断是否绝对值全部相等
ok = 0;
break;
}
}
if (abs(zsnum - fsnum) > 1 && zsnum && fsnum) {puts("No"); continue;}
if (ok) {puts("Yes"); continue;}
std::sort(g, g + n, [] (long long a, long long b) -> bool {return abs(a) < abs(b);}), ok = 1;
for (int i = 1; i < n - 1; ++i) if (g[i-1] * g[i + 1] != g[i] * g[i]) {ok = 0; break;} //枚举判断
puts(ok ? "Yes" : "No");
}
}