1 条题解

  • 0
    @ 2025-11-26 21:09:14

    Written by @Yue_chen

    题意:

    给定一个长度为 n 的数组,和一个 p。

    找长度为3。公比为p的子序列的个数。

    思路:

    直接枚举肯定超时。

    枚举第一个数或最后一个数不能保证另外两个数的顺序,因此枚举中间的数,保证统计的子序列不重复,并且有序。

    所以我们需要时刻保存前缀和后缀。

    枚举时,在后缀中查找a[i] * p的数量,在前缀中查找 a[i]/p的数量,如果a[i]%p != 0 直接跳过。

    合法时直接 ans += 前缀合法数量 * 1 * 后缀合法数量。

    时间复杂度O(nlog2n)

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    using i64 = long long;
    
    void solve() {
        int n, p; cin>>n>>p;
        
        map<i64, i64> mp1, mp2;//mp1为前缀,mp2为后缀
        vector<int> a(n+1);
        for(int i=1; i<=n; ++i) {
            cin>>a[i];
            mp2[a[i]]++;
        }
        
        i64 ans = 0;
        for(int i=1; i<=n; ++i) {//枚举中间的数
            mp2[a[i]]--;
            if(a[i]%p == 0) {
                i64 pre = 1ll * a[i] / p;
                i64 suf = 1ll * a[i] * p;
                if(mp1.count(pre) and mp2.count(suf)) {
                    ans += mp1[pre] * mp2[suf];
                }
            }
            mp1[a[i]]++;
        }
        
        cout<<ans<<"\n";
    }
    
    signed main(void) {
        ios::sync_with_stdio(false); cin.tie(nullptr);
        
        int t=1; //cin>>t;
        while (t--) solve();
        return 0;
    }
    
    • 1

    信息

    ID
    121
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    26
    已通过
    5
    上传者