首页 > 其他分享 >[ARC 188A] ABC Symmetry

[ARC 188A] ABC Symmetry

时间:2025-01-18 17:43:28浏览次数:1  
标签:字符 ABC 前缀 Symmetry int lst ARC 情况 dp

solution by XiangXunYi

思路推导

step 1

首先题目中操作二同时删掉 ABC 的条件相当于同时将三者数量减一,操作一删掉两个相同字符等同于将某一字符的数量减二,那么我们可以发现只使用操作一不会改变奇偶,操作二则是同时反转奇偶,所以一个字符串是个好字符串的必要条件是其中三个字母数量的奇偶性相同,同时容易构造出一组解使其变为空字符串,故也是必要条件。
构造解:执行操作一直到不能执行为止,最后视情况执行操作二。

step2

由于题目的抽象数据范围较小且对于问号的抉择相互影响较大,联想到 dp。首先会想到把 \(K\) 放入 dp 状态中来 check 是否合法,但我们发现每次新增一个字符时算贡献是需要枚举之前前缀三个字符的奇偶性,但上一个状态又并不完全由所枚举的单个状态转移过来,dp 的转移就很扑朔迷离(至少我是这样)。所以要改变 dp 的定义,但又要计算好子段个数,所以状态必须能计算 \(K\) 值。

step 3

设一段区间 A 的数量对 \(2\) 取模为 \(a\),B 的数量对 \(2\) 取模为 \(b\),C 的数量对 \(2\) 取模为 \(c\)。
因为好字段必须要三个字符数量奇偶性相同,抽象的理解为 \(0/1\) 状态,即区间和为 \(0\),前缀和呀!只要两点的前缀和值相等,这个区间就是一个好子段。我们设计一个 dp 状态 \(dp_{i,j,k,l,0/1/2/3}\) 表示存在 \(i\) 个位置前缀区间满足情况 \(0\)[1],\(j\) 个位置前缀区间满足情况 \(1\)[2],\(k\) 个位置前缀区间满足情况 \(2\)[3],\(l\) 个位置前缀区间满足情况 \(3\)[4]且上一个位置前缀区间满足情况 \(0/1/2/3\) 的方案数。
在这种 dp 状态的设计下,我们可以发现,四种情况不重不漏的涵盖了所有区间,当一个区间满足右端点和左端点减一是同一种情况就是一个好子段,最后好子段的个数就是 \(\frac{i \times (i + 1) + j \times (j - 1) + k \times (k - 1) + l \times (l - 1)}{2}\) 答案即为所有该值大于 \(K\) 的 \(dp_{i,j,k,l,0/1/2/3}\) 累加起来。

step 4

定义有了,该题的转移并不难想,只要根据上一个位置的状态加上当前位置的字符即可转移(给个建议:用刷表)。

solution

定义 \(dp_{i,j,k,l,lst \in \{0/1/2/3\}}\) 表示有 \(i\) 个前缀满足情况 \(0\),\(j\) 个前缀满足情况 \(1\),\(k\) 个前缀满足情况 \(2\),\(l\) 个前缀满足情况 \(3\),上一个前缀的情况为 \(lst\)。
对于当前字符为 A 时,情况 \(0\) 与情况 \(3\) 互换,情况 \(1\) 与情况 \(2\) 互换。
对于当前字符为 B 时,情况 \(0\) 与情况 \(1\) 互换,情况 \(2\) 与情况 \(3\) 互换。
对于当前字符为 C 时,情况 \(0\) 与情况 \(2\) 互换,情况 \(1\) 与情况 \(3\) 互换。

int pos = i + j + k + l;
int tmp[4] = { i, j, k, l };
int x = lst ^ 3, y = lst ^ 1, z = lst ^ 2;
if ((s[pos] == '?' || s[pos] == 'A') && tmp[x] + 1 <= n) {
    tmp[x]++;
    trans(dp[tmp[0]][tmp[1]][tmp[2]][tmp[3]][x] , dp[i][j][k][l][lst]);
    tmp[x]--;
}
if ((s[pos] == '?' || s[pos] == 'B') && tmp[y] + 1 <= n) {
    tmp[y]++;
    trans(dp[tmp[0]][tmp[1]][tmp[2]][tmp[3]][y] ,dp[i][j][k][l][lst]);
    tmp[y]--;
}
if ((s[pos] == '?' || s[pos] == 'C') && tmp[z] + 1 <= n) {
    tmp[z]++;
    trans(dp[tmp[0]][tmp[1]][tmp[2]][tmp[3]][z] , dp[i][j][k][l][lst]);
    tmp[z]--;
}

代码

#include <bits/stdc++.h>
using namespace std;
const int N = 55;
const int mod = 998244353;
int n, least, dp[N][N][N][N][4];
char s[55];
inline void trans(int& x, int y) { x = (x + y) % mod; }
int main() {
    scanf("%d%d%s", &n, &least, s);
    dp[0][0][0][0][0] = 1;
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            for (int k = 0; k < n; ++k)
                for (int l = 0; l < n; ++l)
                    if (i + j + k + l < n)
                        for (int lst = 0; lst < 4; ++lst) {
                            int pos = i + j + k + l;
                            int tmp[4] = { i, j, k, l };
                            int x = lst ^ 3, y = lst ^ 1, z = lst ^ 2;
                            if ((s[pos] == '?' || s[pos] == 'A') && tmp[x] + 1 <= n) {
                                tmp[x]++;
                                trans(dp[tmp[0]][tmp[1]][tmp[2]][tmp[3]][x] , dp[i][j][k][l][lst]);
                                tmp[x]--;
                            }
                            if ((s[pos] == '?' || s[pos] == 'B') && tmp[y] + 1 <= n) {
                                tmp[y]++;
                                trans(dp[tmp[0]][tmp[1]][tmp[2]][tmp[3]][y] ,dp[i][j][k][l][lst]);
                                tmp[y]--;
                            }
                            if ((s[pos] == '?' || s[pos] == 'C') && tmp[z] + 1 <= n) {
                                tmp[z]++;
                                trans(dp[tmp[0]][tmp[1]][tmp[2]][tmp[3]][z] , dp[i][j][k][l][lst]);
                                tmp[z]--;
                            }
                        }
    int ans = 0;
    for (int i = 0; i <= n; ++i)
        for (int j = 0; j <= n; ++j)
            for (int k = 0; k <= n; ++k)
                for (int l = 0; l <= n; ++l)
                    for (int lst = 0; lst < 4; ++lst)
                        if (i + j + k + l == n && i * (i + 1) + j * (j - 1) + k * (k - 1) + l * (l - 1) >> 1 >= least)
                            trans(ans, dp[i][j][k][l][lst]);
    printf("%d\n", ans);
    return 0;
}

  1. \(a = b \ and \ a = c\) ↩︎

  2. \(a = c \ and \ a \neq b\) ↩︎

  3. \(a = b \ and \ a \neq c\) ↩︎

  4. \(a \neq b \ and \ b = c\) ↩︎

标签:字符,ABC,前缀,Symmetry,int,lst,ARC,情况,dp
From: https://www.cnblogs.com/keysky/p/18678649

相关文章

  • [ARC 058 - E]Iroha and Haiku
    传送门解题步骤首先可以发现题目范围非常小,尤其是\(X,Y,Z\),所以考虑类似状压、数位dp、双向搜索等算法。官方题解中给的是数位dp,那我这里就讲讲状压了对于\(N\leq40\),很明显不能对其进行状压并且没意义,那么对于\(X,Y,Z\)呢?因为题目要求连续一段数满足要求,且\(X+Y+Z\leq17,......
  • 科普文:算法和数据结构系列【死磕字典树:字典树的升级版三叉树Ternary Search Tree优化
    概叙科普文:算法和数据结构系列【死磕字典树:来一个英文字母游戏】-CSDN博客科普文:算法和数据结构系列【高效的字符串检索结构:字典树Trie树原理、应用及其java示例代码解读】-CSDN博客‌原理‌:Trie树利用字符串之间的公共前缀来减少不必要的字符串比较,从而提高查询效率。每个......
  • 工具 | StarCodeSecurity
    0x00简介StarCodeSecurity是一款图形化的代码审计工具。下载地址:StarCodeSecurity下载:StarCodeSecurity下载0x01功能说明支持对规则进行增删改查审计文件后缀审计路径关键字禁止审计路径关键字支持java、php、net项目审计注:仅供安全研究与学习之用,若将工......
  • ElasticSearch metrics aggregations(度量聚合)
    目录metricsaggregations(度量聚合)avg(平均聚合)脚本(script)值脚本(valuescript)缺失的值(missingvalue)weighted_avg(加权平均聚合)例子脚本(script)缺失的值(missingvalues)boxplot(箱线图聚合)语法脚本(script)箱线图的值(通常)是近似值压缩(compression)缺失的值cardina......
  • ElasticSearch 桶(bucket)聚合
    目录桶(bucket)聚合adjacency_matrix聚合使用Limitationsauto_date_histogram(自动间隔的日期直方图聚合)键(key)间隔(interval)时区(timezone)脚本参数minimum_interval缺失的值children聚合composite(复合聚合)值的来源(valuesource)terms(词项)histogram(直方图)datehistog......
  • ElasticSearch Aggregations(聚合)
    目录Aggregations(聚合)构建聚合值的来源Aggregations(聚合)聚合框架有助于提供基于搜索查询的聚合数据。它基于被称为聚合(aggregations)的简单构建块,可以组合这些块来构建复杂的数据摘要。聚合可以被看作是在一组文档上构建分析信息的工作单元。执行的上下文定义了这个文档......
  • AtCoder Regular Contest 058 [ARC058] F - Unhappy Hacking
    题意:有三种操作,在右边添加0/1或删除最右边的数(空字符串无操作)给出操作数\(N\),字符串\(s\),问有多少种方法经过\(N\)次操作后得到字符串\(S\)思路最开始在想三维dp,虽然发现了性质,但是没想到很好的用法重要性质:答案与字符串内容无关,仅与字符串长度有关定义\(f_{i,j}\)为操作\(i......
  • [ARC108F] Paint Tree
    前言复习什么的就留到下周了,顺便把格式调好现在把每日一练打了差不多今天补了一下午的\(\rm{T2}\),终于还是被码力问题击碎了,不过也还好这道题是模拟赛\(\rm{T3}\)吉司机线段树和左偏树都只能明天搞了,明天把\(\rm{C}\)打了开摆思路首先那几个\(\rm{subtask}\)......
  • Arc B570:英特尔的中端“战锤”能否撼动 200 美元显卡市场?
    前言:新晋“挑战者”,中端GPU市场一夜变天?“200美元显卡市场已经死气沉沉?”或许在2024年底之前,真相并非如此。继ArcB580以出乎意料的高性价比拿下口碑与销量后,英特尔又锻造了一把新的“战锤”——ArcB570。它的目标非常明确:在NVIDIA和AMD低端产品线尚未更新、空当......
  • elasticsearch之数据聚合
    **聚合(aggregations)**可以让我们极其方便的实现对数据的统计、分析、运算。例如:什么品牌的手机最受欢迎?这些手机的平均价格、最高价格、最低价格?这些手机每月的销售情况如何?实现这些统计功能的比数据库的sql要方便的多,而且查询速度非常快,可以实现近实时搜索效果。聚合的种......