[ARC 188A] ABC Symmetry
solution by XiangXunYi
思路推导
step 1
首先题目中操作二同时删掉 A,B,C 的条件相当于同时将三者数量减一,操作一删掉两个相同字符等同于将某一字符的数量减二,那么我们可以发现只使用操作一不会改变奇偶,操作二则是同时反转奇偶,所以一个字符串是个好字符串的必要条件是其中三个字母数量的奇偶性相同,同时容易构造出一组解使其变为空字符串,故也是必要条件。
构造解:执行操作一直到不能执行为止,最后视情况执行操作二。
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;
}
[ARC 188A] ABC Symmetry的更多相关文章
- Atcoder Rating System
来翻译一下官方文档,但是建议看英文原文,本文可能会出现一些错误,只是为了方便自己查阅用的. 对于你的每一场rated比赛,会有一个Performance值\(X_i\),你的rating是\(X_i- ...
- Solution -「ARC 110E」Shorten ABC
\(\mathcal{Description}\) Link. 给定长度为 \(n\),包含 A, B, C 三种字符的字符串 \(S\),定义一次操作为将其中相邻两个不相同的字符替换为字符集 ...
- iOS阶段学习第21天笔记(ARC内存管理-Copy-代理)
iOS学习(OC语言)知识点整理 一.OC 中的ARC内存管理 1)ARC中释放对象的内存原则:看这个对象有没有强引用指向它 2)strong:强引用,默认情况下的引用都是强引用 3) weak:弱引 ...
- 【iOS开发-33】学习手动内存管理临时抛弃ARC以及retain/assign知识——iOSproject师面试必考内容
我们为什么须要内存管理?当使用内存达到40M和45M时候会发出警告,假设不处理,占用内存达到120M时直接强制关闭程序. 所以出现闪退除了是程序出现逻辑错误,还有可能是内存使用过大. (1)创建一个对 ...
- 1.ARC下是否有内存溢出等问题 2.@property参数 3.#import和@class的区别
1.ARC下是否有内存溢出等问题? 答案:必须要担心啊,ARC也不是万能的.答案:必须要担心啊,ARC也不是万能的.这里主要是涉及到集合类的数据类型 比如数组,我们定义了一个可变数组muarr1, ...
- [题解] Atcoder Regular Contest ARC 147 A B C D E 题解
点我看题 A - Max Mod Min 非常诈骗.一开始以为要观察什么神奇的性质,后来发现直接模拟就行了.可以证明总操作次数是\(O(nlog a_i)\)的.具体就是,每次操作都会有一个数a被b取 ...
- Convert BSpline Curve to Arc Spline in OpenCASCADE
Convert BSpline Curve to Arc Spline in OpenCASCADE eryar@163.com Abstract. The paper based on OpenCA ...
- 黑马程序员——ARC机制总结和用ARC建立模型
ARC 全称:Automatic Reference Counting 使用ARC 只需要在建立一个新的项目的时候把 下面的√打上 Xcode5以后都会默认建议开发者使用ARC机制 新的项目中如果有部 ...
- 【IOS】将一组包含中文的数据按照#ABC...Z✿分组
上一篇文章[IOS]模仿windowsphone列表索引控件YFMetroListBox里面 我们一步步的实现了WindowsPhone风格的索引. 但是有没有发现,如果你要实现按照字母排序,你还得自 ...
- JSONKit在项目中使用设置(ARC与方法更新)
在项目中经常会遇到解析json的情况,如果有同学想要解析JSON,那么JSONKit可以是一个不错的选择. git中JSONKit 的地址为:https://github.com/johnezang/ ...
随机推荐
- MindSpore-2.4版本中的一些新特性
技术背景 在前面的一篇博客中我们介绍了MindSpore-2.4-gpu的安装和其中可能出现的一些问题.这里我们在安装完成之后,可以尝试使用一些MindSpore新版本的特性.那么在安装之后,如果是使 ...
- 在 ASP.NET Core 中创建 gRPC 客户端和服务器
前言 gRPC 是一种高性能.开源的远程过程调用(RPC)框架,它基于 Protocol Buffers(protobuf)定义服务,并使用 HTTP/2 协议进行通信. 新建项目 新建解决方案Grp ...
- PC自动化之pywinauto
官方文档: https://pywinauto.readthedocs.io/en/latest/contents.html [安装] pip install pywinauto [使用] from ...
- ZCMU-1038
其实感觉不太难,读懂题意就行,我一开始没有仔细去读感觉就很懵.其题目意思就是一段字符串含有数字和'<'或者'>',一开始从左开始遍历,遇到'>'这类东西换方向,如果有多次遇到就删之前 ...
- Winform多线程持续读取PLC数据
1.Winform窗体界面 2.后台代码 点击查看代码 using Modbus.Device; using System; using System.Collections.Generic; usi ...
- 从底层源码深入分析Bean的实例化
生命周期的整体流程 Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁. ...
- win10 ocx控件注册失败的解决办法
首先注意:ocx放在大部分系统目录无法注册,比如program file ,但windows目录可以. 第一步:关闭防火墙 第二步:确定是否缺少控件运行需要的微软运行库或其他运行环境 这里提供一个挺全 ...
- 【NAS】Docker Gitea+SakuraFrp+绿联DPX4800标 搭建私有代码托管平台
本文主要分享 Gitea的一些设置,和Https的实现. Gitea的一些设置 映射 网络 HTTPS的实现 先准备好一个域名,建议准备一个1Panel 创建一个AC账户然后点击申请证书,手动解析. ...
- tc端口流量控制(带宽限速)
tc qdisc add dev ens192 root handle 1: htbtc class add dev ens192 parent 1: classid 1:1 htb rate 80m ...
- 组件漏洞测试工具---Dependency-Check
目录 文章综述 Dependency-Check简介 工作原理 常用命令 报告解读 使用场景 缺点 文章综述 本文主要介绍Dependency-Check工具的工作原理和使用方法,并提供一个开源方案帮 ...