公式

G - Make Geometric Sequence 解説 by MMNMM


絶対値が \(1\) より大きい公比をもつ等比数列は、全体を反転することで公比の絶対値が \(1\) 未満である等比数列とすることができます。

よって、並べ替えることで公比の絶対値が \(1\) 以下の等比数列にできるかを判定すればよいです。

まず、公比の絶対値が \(1\) であるかを判定します。 \(r=1\) のとき、列はすべて同じ値です。 \(r=-1\) のとき、ある整数 \(x\) が存在して、列は \(\lceil N/2\rceil\) 個の \(x\) と \(\lfloor N/2\rfloor\) 個の \(-x\) からなります。 これらを満たすかどうかは \(O(N)\) 時間で判定できます。

公比の絶対値が \(1\) 未満である等比数列は、値の絶対値が単調減少するため、\(A\) について絶対値の降順でソートした列が等比数列であるかを判定すればよいです。

実装例は以下のようになります。

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    using namespace std;
    unsigned T;
    cin >> T;
    for (unsigned t{}; t < T; ++t) cout << ([]{
        unsigned N;
        cin >> N;
        vector<long> A(N);
        for (auto&& a : A)
            cin >> a;

        // すべて同じ値なら、Yes
        if (ranges::count(A, A[0]) == N)
            return true;

        // 先頭とその -1 倍しかなく、それぞれ ceil(N/2) 個と floor(N/2) 個なら、Yes
        if (const auto p_cnt{ranges::count(A, A[0])}, n_cnt{ranges::count(A, -A[0])}; p_cnt + n_cnt == N && min(p_cnt, n_cnt) == N / 2)
            return true;

        // 絶対値の降順にソートしておく
        ranges::sort(A, greater{}, [](const auto a){ return abs(a); });

        // 公比の絶対値が 1 でないなら、絶対値でソートしたときに等比数列である必要がある
        for (unsigned i{}; i + 2 < N; ++i)
            if (A[i] * A[i + 2] != A[i + 1] * A[i + 1])
                return false;
        return true;
    }() ? "Yes" : "No") << endl;
    return 0;
}

投稿日時:
最終更新: