• 地精部落


    地精部落

    [Ameiyo ]


    求一个序列满足,每个点两边与其大小关系相同

    考虑一个 $ Dp $ , $ f[i][j][0/1] $ 表示比上一个大的数有 $ i $ 个,比他小的数有 $ j $ 个,并且上上个和上一个的关系是 $ 0 $

    那么 $ 0 $ 只能转移到 $ 1 $ , $ 1 $ 只能转移到 $ 0 $

    每次枚举相对距离 $ x $ ,以 $ 0 $ 为例

    [f[i][j][0] -> f[i - x][j + x - 1][1] (1 <= x <= i) ]

    这不像是一个可以优化的东西。。。

    换一下, $ f[i][j][0/1] $ 表示放了 $ i $ 个,比第 $ i $ 个数大的数有 $ j $ 个,其他同上

    同理

    [f[i][j][0] -> f[i + 1][j - x][1] (1 <= x <= j) ]

    在计算 1 的情况时,先算出比第 $ i $ 个小的数量 $ d = n - i - j $

    新的比他小的数量就是 $ d - x (1 <= x <= d) $

    那么新的比他大的数量就是

    [n - (i + 1) - (d - x) = n - (i + 1) - (n - i - j - x) = j + x - 1 ]

    [f[i][j][1] -> f[i][j + x - 1][0] (1 <= x <= n - i - j) ]

    所以

    [f[i][j][1] = sum f[i - 1][j + x][0] ]

    [f[i][j][0] = sum f[i - 1][j - x + 1][1] ]

    复杂度 $ O(n ^ 2) $

    int n, Mod, f[N][N][2];
    
    int main() {
        n = read<int>(), Mod = read<int>();
        rep (j, 0, n - 1) f[1][j][0] = f[1][j][1] = 1;
        rep (i, 2, n) {
            int sum = 0;
            dep (j, n - i + 1, 0) {
                f[i][j][0] = sum;
                ((sum += f[i - 1][j][1]) >= Mod && (sum -= Mod));
            }
            sum = 0;
            rep (j, 0, n - i + 1) {
                ((sum += f[i - 1][j][0]) >= Mod && (sum -= Mod));
                f[i][j][1] = sum;
            }
        }
    
        printf("%d
    ", (f[n][0][0] + f[n][0][1]) % Mod);
        return 0;
    }
    
    

    [in 2019.10.31 ]

  • 相关阅读:
    2.4 学习总计 之 自己实现底部导航
    2.3 学习总结 之 分页查询
    2.2 学习总结 之 servlet 的两次抽取
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
    Rocket
  • 原文地址:https://www.cnblogs.com/Ameiyo/p/11771465.html
Copyright © 2020-2023  润新知