• Educational Codeforces Round 118 (Rated for Div. 2) D. MEX Sequences


    \(DP\)真的太难了啊!!
    首先考虑到\(f(i, s)\)表示,从前\(i\)个数中选,最后一个数为\(a_i\),且\(MEX(a_1,....,a_i) = \left\{ \begin{aligned} a_{i} - 1 (s = 0) \\ a_{i} + 1(s = 1)\end{aligned} \right.\),因为有\(a_i\)的存在,那么\(MEX\)只能取这两种值。
    列出方程:

    \[f(i, a[i] - 1) = \sum\limits_{j = 1}^{i - 1}f(j, a[j] - 1)[a_j == a_i] + \sum\limits_{j = 1}^{i - 1}f(j, a[j] + 1)(a_j == a_i - 2) \]

    \[f(i, a[i] + 1) = \sum\limits_{j = 1}^{i - 1}f(j, a[j] - 1)[a_j == a_i + 2] + \sum\limits_{j = 1}^{i - 1}f(j, a_j + 1)(a_j == a_i) \]

    但是这样需要\(O(n ^ 2)\)复杂度。

    而发现给定的\(a_i\)值很小,因此可以直接把这个作为状态。

    \(f(j, s)\)表示从前i个数中选,\(MEX(...a_k) = j\),且最后一个数为\(a_k\)\(a_k = \left\{ \begin{aligned} j - 1 (s = 0) \\ j + 1(s = 1)\end{aligned} \right.\)的方案数,那么当前x影响的只有\(f(x + 1, s)\)\(f(x - 1, s)\)这两种方案,这样复杂度就降为了\(O(n * 2)\)

    下面进行分类讨论:
    1. 若\(MEX = x + 1\),最后一个数为\(x\)的方案。
    1.1 前\(i - 1\)个数\(MEX = x + 1\),最后一个数为\(x\)的方案。
    1.2 前\(i - 1\)个数\(MEX = x + 1\),最后一个数为\(x\),再添加一个\(x\)的方案。
    1.3 前\(i - 1\)个数\(MEX = x\),最后一个数为\(x - 1\),再添加一个\(x\)的方案。
    那么方程如下:

    \[f(x + 1, 0) = 2 * f(x + 1, 0) + f(x, 0) \]

    2. 若\(MEX = x + 1\),最后一个数为\(x + 2\)的方案。
    2.1 前\(i - 1\)个数\(MEX = x + 1\),最后一个数为\(x + 2\)的方案。
    2.2 前\(i - 1\)个数\(MEX = x + 1\),最后一个数为\(x + 2\),再添加一个\(x\)的方案。
    那么方程如下:

    \[f(x + 1, 1) = 2 * f(x + 1, 1) \]

    3. 若\(MEX = x - 1\),最后一个数为\(x\)的方案。
    3.1 前\(i - 1\)个数\(MEX = x - 1\),最后一个数为\(x\)的方案。
    3.2 前\(i - 1\)个数\(MEX = x - 1\),最后一个数为\(x\),再添加一个\(x\)的方案。
    3.3 前\(i - 1\)个数\(MEX = x - 1\),最后一个数为\(x - 2\),再添加一个\(x\)的方案。
    那么方程如下:

    \[f(x - 1, 1) = 2 * f(x - 1, 1) + f(x - 1, 0) \]

    #include <bits/stdc++.h>
    
    using namespace std;
    
    using ll = long long;
    const int Mod = 998244353;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        int t;
        cin >> t;
        while (t--) {
            //memset(f, 0, sizeof f);
            int n;
            cin >> n;
            vector<int> a(n);
            for (int i = 0; i < n; i++) {
                cin >> a[i];
            }
            vector<vector<ll>> f(n + 2, vector<ll>(4, 0));
            f[0][0] = 1;
            //f[0][1] = ;
            for (int i = 0; i < n; i++) {
                int x = a[i];
                f[x + 1][0] = (f[x + 1][0] * 2 % Mod + f[x][0]) % Mod;
                f[x + 1][1] = f[x + 1][1] * 2 % Mod;
                
                if (x > 0) {
                    f[x - 1][1] = (f[x - 1][1] * 2 % Mod + f[x - 1][0]) % Mod;
                }
            } 
            
            ll res = 0;
            for (int i = 0; i <= n; i++) {
                res = (res + f[i][0] + f[i][1]) % Mod;
            }
    
            cout << (res - 1 + Mod) % Mod << "\n";
        }
    
        return 0;
    }
    
  • 相关阅读:
    金山词霸注册表怎么删
    新手学习jquery
    《企业应用架构模式》(POEAA)读书笔记
    Silverlight 4 tools
    asp.net非常基础的面试题
    VS 2010 中文版正式版无法安装Silverlight4 Tools的解决办法
    OnPreRender(EventArgs e) 事件常用的方法
    各大搜索引擎网站登录入口
    向用户控件传递参数的问题
    URLRewriter
  • 原文地址:https://www.cnblogs.com/ZhengLijie/p/16225725.html
Copyright © 2020-2023  润新知