首页 > 其他分享 >CF2004G 题解

CF2004G 题解

时间:2024-09-19 22:15:05浏览次数:10  
标签:std infty min int 题解 CF2004G res ldots

题意

定义关于数字串 \(s\) 的函数 \(f(s)\) 表示将 \(t\) 切分为 \(m\) 段,要求 \(m\) 是偶数,假设这些字符串分别为 \(t_1, t_2, \ldots, t_m\),有 \(s = t_1 + t_2 + \ldots + t_m\)。定义 \(A^x\) 表示 \(\underbrace{AA\ldots AA}_{x~\text{times}}\),求一种划分方式,使得 \(t_2^{t_1} + t_4^{t_3} + \ldots + t_m^{t_{m - 1}}\) 最短。

现在给定长度为 \(n\) 的字符串 \(S\) 和一个正整数 \(k\),对每个 \(i = 1, 2, \ldots, n - k + 1\),求出 \(f(s[i, i + 1, \ldots, i + k - 1])\)。

首先考虑 \(k = n\) 的情况,容易观察到对于 \(i\) 为奇数,\(t_i\) 一定小于 \(10\),否则可以将后一位分给 \(t_{i + 1}\),一定更优。根据该性质,可以考虑 dp 并设计出 dp 方程,设 \(f_{i, j}\) 表示考虑前 \(i\) 位,现在的 \(t_{k}\) 等于 \(j\) 的答案,有转移:

  • 刚刚结束一段 \(t_k\),则 \(j = 0\),有 \(f_{i, j} = \min\{f_{i - 1, k} + k\}\),其中 \(k \in [1, 9]\)。
  • 延续关于 \(t_k\) 的选择,对于 \(j \in [1, 9]\),有 \(f_{i, j} = \min\{f_{i - 1, j} + j\}\)。
  • 开始一段新的 \(t_k\),有 \(f_{i, t_j} = \min\{f_{i - 1, 0}\}\)。

答案是 \(f_{n, 0}\)。

注意到这个转移是可以矩乘辅助转移的,可以设计出矩阵:

\[\begin{bmatrix} f_{i, 0} & f_{i, 1} & f_{i, 2} & \ldots & f_{i, 9} \end{bmatrix} \times \begin{bmatrix} +\infty & +\infty & +\infty & \ldots & +\infty \\ 1 & 1 & +\infty & \ldots & +\infty\\ 2 & +\infty & 2 & \ldots & +\infty\\ \vdots & \vdots & \vdots & \ddots & \vdots\\ 9 & +\infty & +\infty & \ldots & 9 \end{bmatrix} = \begin{bmatrix} f_{i + 1, 0} & f_{i + 1, 1} & f_{i + 1, 2} & \ldots & f_{i + 1, 9} \end{bmatrix} \]

要把转移矩阵的第一行第 \(t_i\) 列设成 \(0\),注意这里的矩阵乘法为 \((\min, +)\) 运算,即 \(A \times B = C\) 实际上是:

\[C_{i, j} = \min_{k = 0}^9 A_{i, k} + B_{k, j} \]

设 \(w = 10\),可以在 \(O(nw^3)\) 的复杂度内计算出 \(k = n\) 时的答案,考虑扩展到 \(k < n\) 的情况。

有一个经典 trick(这个 trick 在 P6717P1117 中都有运用),就是将序列按照块长为 \(k - 1\) 分为若干块,这样每一个长度为 \(k\) 的子区间一定都是一块的前缀和一块的后缀拼起来的。

所以可以预处理每个块的前缀积和后缀积,每次查询时乘起来即可。时间复杂度仍为 \(O(nw^3)\)。

但 \(O(nw^3)\) 常数过大,写出来会被卡常,考虑优化。由于矩阵中只有 \(O(w)\) 个位置不是 \(+\infty\),所以对这 \(O(w)\) 个位置分别转移即可,时间复杂度优化到了 \(O(nw^2)\),可以通过。

代码
#include <bits/stdc++.h>

using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;

constexpr int N = 10;

constexpr int inf = 1E9;

struct Matrix {
    std::vector<std::vector<int>> a;

    Matrix() {
        Init(0);
    }
    Matrix(int k) {
        Init(k);
    }

    void Init(int k) {
        a.assign(N, std::vector<int>(N, inf));
        if (k == 1) {
            for (int i = 0; i < N; ++i) {
                a[i][i] = 0;
            }
        }
    }

    auto &operator[](int x) {
        return a[x];
    }
} ;

Matrix appendr(Matrix pre, int x) {
    Matrix res;
    
    for (int i = 0; i < N; ++i) {
        for (int j = 1; j < N; ++j) {
            res[i][0] = std::min(res[i][0], pre[i][j] + j);
            res[i][j] = std::min(res[i][j], pre[i][j] + j);
        }
    }
    for (int i = 0; i < N; ++i) {
        res[i][x] = std::min(res[i][x], pre[i][0]);
    }

    return res;
}

Matrix appendl(Matrix pre, int x) {
    Matrix res;

    for (int i = 1; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            res[i][j] = std::min(res[i][j], i + std::min(pre[0][j], pre[i][j]));
        }
    }

    for (int i = 0; i < N; ++i) {
        res[0][i] = std::min(res[0][i], pre[x][i]);
    }

    return res;
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int n, k;
    std::cin >> n >> k;
    
    std::string s;
    std::cin >> s;

    std::vector<Matrix> suf(n);

    for (int l = 0, r = 0; l < n; l = r + 1) {
        r = std::min(n - 1, l + k - 2);

        Matrix res = 1;
        for (int i = l; i <= r; ++i) {
            res = appendr(res, s[i] - '0');
            if (i + 1 >= k) {                  
                int ans = inf;
                for (int x = 0; x < N; ++x) {
                    ans = std::min(ans, suf[i - k + 1][0][x] + res[x][0]);
                }
                std::cout << ans << " ";
            }
        }

        suf[r] = 1;
        for (int i = r; i >= l; --i) {
            suf[i] = appendl(suf[i + (i < r)], s[i] - '0');
        }
    }

    return 0;
}

标签:std,infty,min,int,题解,CF2004G,res,ldots
From: https://www.cnblogs.com/CTHOOH/p/18421472

相关文章

  • P1108 低价购买 题解
    这题在求最长下降子序列的基础上加了一个求方案数的要求,这就让这道题目变难了很多。我们考虑我们在求最长下降子序列的时候,总是从这一位,要么重新开始计数,要么只和前面的有关,所以前面的信息完全丢失了,无法判断有多少方案,所以我们就要针对前面的方案数设计一个dp来统计。可以称之......
  • 题解:CF1906F Maximize The Value
    可以在cnblog中阅读。见这种题比较少,写篇题解加深印象。如果直接上数据结构维护数组,似乎没有好的办法处理操作序列的一个子段。那不妨转变思路,对操作序列上数据结构维护。假设顺序进行每个修改操作,我们用时间表示修改操作的编号,位置表示数组的下标,则常见的维护序列的数据结构......
  • 蓝桥杯十五届软件赛C++B组题解
    最近蓝桥杯官网已经把十五届题目上架了,我会尽快的将题解发出来,没有发的过段时间再补。​​​​​​​数字接龙一个很鹅心的搜索题,一不注意就会写错,比赛的时候写不来,题目上架后也WA了两个样例才过。题目大意:也就是说从(1,1)开始 ,下一步路的数据总是要比当前数据大1,超过k就......
  • P2051 [AHOI2009] 中国象棋 题解
    DP好题?首先确定,每一行/列只能放至多两个棋子,这么少,所以我们的状态肯定和棋子数有关。由于我们不关注具体的方案数,所以我们不妨只关心对应棋子数量的行/列的数量。同时,由于考虑行和列都是一样的,所以我们不妨用行递推。所以我们设$\dp_{i,j,k}\$表示当前放到第\(i\)行,有\(......
  • Capital许可使用常见问题解答
    在使用Capital软件的过程中,许多用户可能会遇到关于许可使用的各种问题。为了帮助大家更好地理解和合规使用Capital软件,我们整理了一份常见问题解答,希望能为您提供有价值的参考。一、Capital许可证的类型有哪些?Capital提供多种许可证类型,包括永久许可证、订阅许可证等。永久许可......
  • 【题解】Solution Set - NOIP2024集训Day32 数位 dp
    【题解】SolutionSet-NOIP2024集训Day32数位dphttps://www.becoder.com.cn/contest/5537order:1,3,5,6,2,4「SDOI2013」淘金就是要算前\(k\)大的和。考虑一个位置\((i,j)\)在变化完了之后的金子个数。(也即逆变换。设:\(f^\prime(x)\)表示在\(1\simN\)范围内,数位......
  • 【洛谷 P5730】【深基5.例10】显示屏 题解(数组+循环)
    【深基5.例10】显示屏题目描述液晶屏上,每个阿拉伯数字都是可以显示成的点阵的(其中X表示亮点,.表示暗点)。现在给出数字位数(不超过)和一串数字,要求输出这些数字在显示屏上的效果。数字的显示方式如同样例输出,注意每个数字之间都有一列间隔。输入格式第一行输入一个正整数,表示数......
  • luogu-P10596题解
    简要题意一个有\(N\)个元素的集合有\(2N\)个不同子集(包含空集),现在要在这\(2N\)个集合中取出若干集合(至少一个),使得它们的交集的元素个数为\(K\),求取法的方案数,答案模\(10^9+7\)。数据范围:\(1\leK\leN\le10^6\)。题解我们设\(f(i)\)表示选出子集大小恰好为\(i\)的......
  • 【洛谷】P11062 【MX-X4-T2】「Jason-1」加法 的题解
    【洛谷】P11062【MX-X4-T2】「Jason-1」加法的题解题目传送门离CSP初赛只剩两天了,祝各位OIersrp++!!!题解挺有意思的一道思维题,不过比赛的时候没想出来。需要分类讨论两种情况:当a......
  • ICPC2021 沈阳站 M String Problem 题解 | 十种做法一网打尽 , 一道题带你回顾字符串科
    题目传送门题意给定一个字符串,求每个前缀的字典最大序子串。注意到:对于每个前缀$s_{[1,i]}$,字典序最大子串的右边界一定是\(i\)。随着着\(i\)的增大,字典序最大子串的左边界一定是单调不减的。解法不分先后。后缀数组SASA&SAM后缀数组&后缀自动机SA对所有......