• H


    2019ECfinal

    https://vjudge.net/contest/406509#overview

    H - King

    题目大意

    给定长度为(n)的序列(A)

    (A)的最长子序列(B),满足以下条件,最长为多少?

    [B=(b_1,b_2,..,b_m) ]

    [forall i in [2,m],q b_{i-1}equiv b_i pmod p. ]

    如果最大长度小于(frac{n}{2}),则直接输出(-1)

    题目解法

    关键限制条件为子序列只有长度够(frac{n}{2})才算满足要求

    因此其中出现在(B)中概率最大的为(A)中邻近的两个位置((a_i,a_{i+1}))或者((a_i,a_{i+2}))

    (unordered\_map)对于这些点对求出(q)进行计数。

    如果要满足答案,对应(q)的数量至少为

    [lfloor frac{n+3}{4} floor -1 ]

    对于所有满足条件的(q)进行验证,最多验证(8)次。

    时间复杂度(O(nlog(n)))

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 2e5 + 5;
    int a[N], mod;
    unordered_map<int, int> qNum, qLen;
    int myPow(int p, int q)
    {
        int re = 1;
        for (; q; q >>= 1)
        {
            if (q & 1)
                re = (ll)re * p % mod;
            p = (ll)p * p % mod;
        }
        return re;
    }
    int calcQ(int a1, int a2)
    {
        return (ll)a2 * myPow(a1, mod - 2) % mod;
    }
    int main()
    {
        freopen("h.in", "r", stdin);
        int T;
        cin >> T;
        while (T--)
        {
            qNum.clear();
            int n, minLen, ans = 0;
            cin >> n >> mod;
            minLen = (n + 1) / 2;
            for (int i = 1; i <= n; ++i)
                cin >> a[i];
            for (int i = 1; i < n; ++i)
            {
                int q = calcQ(a[i], a[i + 1]);
                qNum[q]++;
                //cout << q<< ' ';
            }
            for (int i = 1; i + 2 <= n; ++i)
            {
                int q = calcQ(a[i], a[i + 2]);
                qNum[q]++;
                //cout << q<< ' ';
            }
            //cout << endl;
            for (auto i : qNum)
            {
                //cout << '(' << i.first << ',' << i.second << endl;
                if (i.second + 1 < (n + 3) / 4)
                    continue;
                qLen.clear();
                int q = i.first;
                for (int j = 1; j <= n; ++j)
                {
                    int baseLen = 0;
                    if (qLen.find(a[j]) != qLen.end())
                    {
                        baseLen = qLen[a[j]];
                    }
                    qLen[(ll)a[j] * q % mod] = baseLen + 1;
                    ans = max(ans, baseLen + 1);
                }
            }
            if (ans >= minLen)
                cout << ans << endl;
            else
                cout << -1 << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    Eclipse项目上传和下载到码云上
    java.lang.IllegalArgumentException,java.util.zip.ZipException 解决办法
    #{}和${}的区别
    Lambda 表达式
    存储器的按字寻址和按字节寻址
    二叉树的三种遍历方式
    线性表和链表
    java泛型理解
    java字符输入输出流
    applet的生命周期
  • 原文地址:https://www.cnblogs.com/bzmd/p/14198488.html
Copyright © 2020-2023  润新知