ARC138 B - 01 Generation 题解

ARC138 B - 01 Generation

思路

考虑逆向思维,很容易想到可以优先从后面删掉0(操作B的逆向操作),然后如果前面是0则删掉它并将序列翻转(操作A的逆向操作),一直重复这两个步骤直到字符串为空。如果中途无法操作,输出No,否则输出Yes

下面我们来证明这个方法的正确性:

  • 首先,假设有一个序列 A A A按照上述方法输出No,但正确答案为Yes
  • 则一定在某一步(可能是第一步)只能先倒推操作A,而不是操作B,设这一步执行前的序列为 S S S
  • 此时,令 N = ∣ S ∣ N=|S| N=S,则 S 1 = S N = 0 S_1=S_N=0 S1=SN=0
  • 如果先倒推操作A,得到 ( S 2 , S 3 , … , S N − 1 , 1 ) (S_2,S_3,\dots,S_{N-1},1) (S2,S3,,SN1,1)
  • 如果先倒推操作B,得到 ( S 1 , S 2 , … , S N − 1 ) (S_1,S_2,\dots,S_{N-1}) (S1,S2,,SN1)
  • 对比两个序列,发现先倒推操作B不会影响后续倒推A的结果,因此,序列 S S S不存在
  • 结论:做法正确。

代码

代码实现时,没有必要真正翻转序列,只需记录当前翻转的状态( 0 0 0 1 1 1),记为 flipped \text{flipped} flipped,则实际的 A i = A i ′ ⊕ flipped A_i=A_i'\oplus\text{flipped} Ai=Aiflipped(其中 A i ′ A_i' Ai为输入的 A A A ⊕ \oplus 表示异或/XOR操作)。

删除时可以使用deque或者数组 l , r l,r l,r端点记录。

#include <cstdio>
#define maxn 200005
using namespace std;

bool a[maxn];

int main()
{
	int n = 0;
	char c;
	while((c = getchar()) != '\n')
		n = (n << 3) + (n << 1) + (c ^ 48);
	for(int i=0; i<n; i++, getchar())
		a[i] = getchar() ^ 48;
	bool flipped = false;
	for(int l=0, r=n-1; a[l]==flipped; flipped^=1, l++)
		while(!a[r] ^ flipped)
			if(l > --r)
				return puts("Yes"), 0;
	puts("No");
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ARC069 D 题目传送门:https://atcoder.jp/contests/arc069/tasks/arc069_b 题目描述: 给定两个长度为 $n$ 的字符串 $s$ 和 $t$,每个字符都是小写字母。你需要找到一个长度为 $n$ 的字符串 $u$,满足: - 对于所有 $i \in [1,n]$,都有 $u_i \in \{s_i,t_i\}$。 - 不存在相邻的字符 $u_i$ 和 $u_{i+1}$ 相等。 求满足条件的字符串 $u$ 的个数,对 $10^9+7$ 取模。 解题思路: 这是一道比较经典的字符串构造问题,可以用 dp 或者数学方法来解决。 方法一:dp 我们可以使用 dp 来解决这个问题。设 $f_{i,j}$ 表示构造了前 $i$ 个字符,第 $i$ 个字符为 $j$,且第 $i-1$ 个字符为 $s_{i-1}$ 或 $t_{i-1}$ 的方案数。其中,$j \in \{s_i,t_i\}$。 状态转移方程如下: $$f_{i,j} = \begin{cases} 1, & i=1, j=s_1 \text{ 或 } j=t_1\\ 0, & i=1, j \neq s_1 \text{ 且 } j \neq t_1\\ \sum\limits_{k \in \{s_{i-1},t_{i-1}\},k \neq j} f_{i-1,k}, & i>1 \end{cases}$$ 最终的答案为 $f_{n,s_n}+f_{n,t_n}$。 时间复杂度为 $O(n)$。 方法二:数学 我们可以发现,对于任意一个长度为 $n$ 的字符串 $s$ 和 $t$,它们的方案数都是 $2^n$。因为对于每个位置,我们都可以选择 $s$ 或 $t$ 中的任意一个字符。 但是,这样计算出来的方案数显然是错误的,因为存在相邻字符相等的限制条件。 考虑将所有满足限制条件的字符串按照第一个字符 $j$ 分类,其中 $j \in \{s_1,t_1\}$。这样,整个字符串集合就被划分为了 $4$ 个子集: - $S_1$:以 $s_1$ 开头,且不存在相邻字符相等的字符串。 - $S_2$:以 $s_1$ 开头,且存在相邻字符相等的字符串。 - $S_3$:以 $t_1$ 开头,且不存在相邻字符相等的字符串。 - $S_4$:以 $t_1$ 开头,且存在相邻字符相等的字符串。 我们需要计算的就是第 $n$ 个位置的字符为 $s_n$ 或 $t_n$,且不存在相邻字符相等的字符串的方案数。 对于 $S_1$,第 $i$ 个字符可以选择 $s_i$ 或 $t_i$,但是由于相邻字符不能相等,所以第 $i+1$ 个字符必须与第 $i$ 个字符不同,因此第 $i+1$ 个字符只有 $2$ 种选择。 对于 $S_2$,第 $i$ 个字符可以选择 $s_i$ 或 $t_i$,但是由于相邻字符必须相等,所以第 $i+1$ 个字符必须与第 $i$ 个字符相等,因此第 $i+1$ 个字符只有 $1$ 种选择。 对于 $S_3$ 和 $S_4$,与 $S_1$ 和 $S_2$ 类似,我们可以得到第 $i+1$ 个字符的选择个数为 $2$ 和 $1$。 综上所述,我们可以得到递推式: $$\begin{cases} a_{i+1} = 2(b_i+c_i+d_i) \\ b_{i+1} = a_i \\ c_{i+1} = 2(a_i+d_i) \\ d_{i+1} = b_i \end{cases}$$ 初始状态为 $a_1=1,b_1=0,c_1=1,d_1=1$。 最终的答案为 $a_n+c_n$。 时间复杂度为 $O(n)$。 代码实现:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值