Atcoder 题面传送门 & 洛谷题面传送门

首先考虑对于固定的 01 串怎样计算它是否可以通过将三个连续的 \(0\) 或 \(1\) 替换为其中位数得到。我们考虑单调栈,新建一个栈,栈底到栈顶分别是一段连续的 \(1\) 和一段连续的 \(0\),分别表示当前未合并完的字符,我们从左往右扫描,每遇到一个字符可分以下两种情况:

  • 如果我们遇到一个 \(0\):

    • 如果栈为空,那直接将这个 \(0\) 入栈就好了。

    • 如果栈顶 \(0\) 的个数 \(\ge 2\),那么显然我们可以把三个连续的 \(0\) 合并成一个 \(0\),因为不论我们后来加入什么样的数字,这样一一合并下去最终只可能得到一个 \(0\),也就是说原来栈顶的两个 \(0\) 变成了一个 \(0\)。

    • 如果栈顶没有 \(0\),否则直接将这个 \(0\) 入栈。

  • 如果我们遇到一个 \(1\):

    • 如果栈为空,那直接将这个 \(1\) 入栈就好了。

    • 如果栈顶有 \(0\),并且栈不为空,那么栈最顶上的两个元素一定是一个 \(0\) 一个 \(1\),而显然如果第一个数是 \(0\),第二个数是 \(1\),那第三个数不论是多少,取中位数得到的结果一定还是第三个数,所以我们索性将最开头的 \(01\) 抵消,也就是说栈中 \(0\) 的个数减少了 \(1\),此时栈底到栈顶还是一段连续的 \(1\) 和一段连续的 \(0\)。

    • 否则,栈中一定只剩一段连续的 \(1\)。如果这段 \(1\) 的个数 \(\ge 3\),仿照之前的推理过程它可以等效于 \(3\) 个 \(1\),否则我们就直接将 \(1\) 入栈。

显然最终栈不为空,并且该 01 串 \(s\) 满足条件的充要条件是最后 \(1\) 的个数大于 \(0\) 的个数,因为如果在合并过程中不存在栈中剩余 \(\ge 3\) 个 \(1\),并且又进来了一个 \(1\) 的情况,那么每次操作栈内数的个数要么 \(+1\) 要么 \(-1\),而 \(n\) 为奇数,故最后栈中剩余数的个数是奇数。如果只剩一个 \(1\) 那就直接满足条件了,如果剩 \(2\) 个 \(1\) 一个 \(0\) 或者 \(3\) 个 \(1\) 把这三个数合并一下即可,如果剩 \(3\) 个 \(1\) 两个 \(0\) 根据抽屉原理一定存在连续的三个数中恰好有 \(2\) 个 \(1\),把这三个数合并得到一个 \(1\),再把剩下三个数合并即可。如果在合并过程中存在栈中剩余 \(\ge 3\) 个 \(1\),并且又进来了一个 \(1\) 的情况,那么最终这三个 \(1\) 一定不会被消掉,也就是说最终 \(1\) 的个数为 \(3\),严格大于 \(0\) 的个数的最大值 \(2\),也符合题意。

接下来考虑原题。不难发现任何时刻单调栈中 \(1\) 的个数 \(\le 3\),\(0\) 的个数 \(\le 2\),也就是说本质不同的单调栈的个数 \(\le 12\)。我们考虑将单调栈放入 DP 状态中,即设 \(dp_{i,x,y}\) 表示考虑到第 \(i\) 个字符,单调栈中还剩 \(x\) 个 \(0\) 和 \(y\) 个 \(1\) 的方案数。分该位填 \(0\) 和该位填 \(1\) 转移即可。复杂度线性。

const int MAXN=3e5;
const int MOD=1e9+7;
int n,dp[MAXN+5][3][4];char s[MAXN+5];
void add(int &x,int v){((x+=v)>=MOD)&&(x-=MOD);}
int main(){
scanf("%s",s+1);n=strlen(s+1);dp[0][0][0]=1;
for(int i=0;i<n;i++) for(int c0=0;c0<3;c0++) for(int c1=0;c1<4;c1++){
if(s[i+1]!='1'){//digit 0
if(c0==2) add(dp[i+1][1][c1],dp[i][c0][c1]);
else add(dp[i+1][c0+1][c1],dp[i][c0][c1]);
} if(s[i+1]!='0'){//digit 1
if(c0) add(dp[i+1][c0-1][c1],dp[i][c0][c1]);
else add(dp[i+1][c0][min(c1+1,3)],dp[i][c0][c1]);
}
} int ans=0;
for(int c1=1;c1<=3;c1++) for(int c0=0;c0<c1;c0++)
add(ans,dp[n][c0][c1]);
printf("%d\n",ans);
return 0;
}

Atcoder Grand Contest 022 E - Median Replace(dp)的更多相关文章

  1. Atcoder Grand Contest 002 F - Leftmost Ball(dp)

    Atcoder 题面传送门 & 洛谷题面传送门 这道 Cu 的 AGC F 竟然被我自己想出来了!!!((( 首先考虑什么样的序列会被统计入答案.稍微手玩几组数据即可发现,一个颜色序列 \(c ...

  2. AtCoder Grand Contest 032 A - Limited Insertion( 思维)

    Time Limit: 2 sec / Memory Limit: 1024 MB Score : 400400 points Problem Statement Snuke has an empty ...

  3. Atcoder Grand Contest 006 D - Median Pyramid Hard(二分+思维)

    Atcoder 题面传送门 & 洛谷题面传送门 u1s1 Atcoder 不少思维题是真的想不出来,尽管在 Atcoder 上难度并不高 二分答案(这我倒是想到了),检验最上面一层的数是否 \ ...

  4. Atcoder Grand Contest 001 F - Wide Swap(拓扑排序)

    Atcoder 题面传送门 & 洛谷题面传送门 咦?鸽子 tzc 来补题解了?奇迹奇迹( 首先考虑什么样的排列可以得到.我们考虑 \(p\) 的逆排列 \(q\),那么每次操作的过程从逆排列的 ...

  5. Atcoder Grand Contest 038 F - Two Permutations(集合划分模型+最小割)

    洛谷题面传送门 & Atcoder 题面传送门 好久前做的题了--今天偶然想起来要补个题解 首先考虑排列 \(A_i\) 要么等于 \(i\),要么等于 \(P_i\) 这个条件有什么用.我们 ...

  6. Atcoder Grand Contest 013 E - Placing Squares(组合意义转化+矩阵快速幂/代数推导,思维题)

    Atcoder 题面传送门 & 洛谷题面传送门 这是一道难度 Cu 的 AGC E,碰到这种思维题我只能说:not for me,thx 然鹅似乎 ycx 把题看错了? 首先这个平方与乘法比较 ...

  7. Atcoder Grand Contest 032 E - Modulo Pairing(乱搞+二分)

    Atcoder 题面传送门 & 洛谷题面传送门 神仙调整+乱搞题. 首先某些人(including me)一看到最大值最小就二分答案,事实上二分答案对这题正解没有任何启发. 首先将 \(a_i ...

  8. 题解——ATCoder AtCoder Grand Contest 017 B - Moderate Differences(数学,构造)

    题面 B - Moderate Differences Time limit : 2sec / Memory limit : 256MB Score : 400 points Problem Stat ...

  9. AtCoder Grand Contest 022

    A - Diverse Word Time limit : 2sec / Memory limit : 256MB Score : 300 points Problem Statement Gotou ...

随机推荐

  1. OO_JAVA_表达式求导_单元总结

    OO_JAVA_表达式求导_单元总结 这里引用个链接,是我写的另一份博客,讲的是设计层面的问题,下面主要是对自己代码的单元总结. 程序分析 (1)基于度量来分析自己的程序结构 第一次作业 程序结构大致 ...

  2. 使用logstash的input file filter收集日志文件

    使用logstash的input file filter收集日志文件 一.需求 二.实现步骤 1.前置知识 2.编写pipeline文件 3.Input 中 file 插件的部分参数解释: 4.启动l ...

  3. MD支持程度测试

    Editor.md 目录 (Table of Contents) [TOCM] 目录 Editor.md Heading 1 Heading 2 Heading 3 Heading 4 Heading ...

  4. C语言基础资料,可以看看哦

    C语言程序的结构认识 用一个简单的c程序例子,介绍c语言的基本构成.格式.以及良好的书写风格,使小伙伴对c语言有个初步认识. 例1:计算两个整数之和的c程序: #include main() { in ...

  5. 常用Java API: ArrayList(Vector) 和 LinkedList

    摘要: 本文主要介绍ArrayList(Vector)和LinkedList的常用方法, 也就是动态数组和链表. ArrayList ArrayList 类可以实现可增长的对象数组. 构造方法 Arr ...

  6. 链地址法查找成功与不成功的平均查找长度ASL

    晚上,好像是深夜了,突然写到这类题时遇到的疑惑,恰恰这个真题只让计算成功的ASL,但我想学一下不成功的计算,只能自己来解决了,翻了李春葆和严蔚敏的教材没有找到相关链地址法的计算,于是大致翻到两篇不错的 ...

  7. 并发编程从零开始(十二)-Lock与Condition

    并发编程从零开始(十二)-Lock与Condition 8 Lock与Condition 8.1 互斥锁 8.1.1 锁的可重入性 "可重入锁"是指当一个线程调用 object.l ...

  8. 高并发场景下JVM调优实践之路

    一.背景 2021年2月,收到反馈,视频APP某核心接口高峰期响应慢,影响用户体验. 通过监控发现,接口响应慢主要是P99耗时高引起的,怀疑与该服务的GC有关,该服务典型的一个实例GC表现如下图: 可 ...

  9. 回文链表 牛客网 程序员面试金典 C++ Python

    回文链表 牛客网 程序员面试金典  C++ Python 题目描述 请编写一个函数,检查链表是否为回文. 给定一个链表ListNode* pHead,请返回一个bool,代表链表是否为回文. 测试样例 ...

  10. 整数转化 牛客网 程序员面试金典 C++ Python

    整数转化 牛客网 程序员面试金典 C++ Python 题目描述 编写一个函数,确定需要改变几个位,才能将整数A转变成整数B. 给定两个整数int A,int B.请返回需要改变的数位个数. 测试样例 ...