Flippy Sequence

ZOJ

DreamGrid has just found two binary sequences s 1 , s 2 , … , s n s_1, s_2, \dots, s_n s1,s2,,sn and t 1 , t 2 , … , t n t_1, t_2, \dots, t_n t1,t2,,tn ( s i , t i ∈ { 0 , 1 } s_i, t_i \in \{0, 1\} si,ti{0,1} for all 1 ≤ i ≤ n 1 \le i \le n 1in) from his virtual machine! He would like to perform the operation described below exactly twice, so that s i = t i s_i = t_i si=ti holds for all 1 ≤ i ≤ n 1 \le i \le n 1in after the two operations.
The operation is: Select two integers l l l and r r r ( 1 ≤ l ≤ r ≤ n 1 \le l \le r \le n 1lrn), change s i s_i si to ( 1 − s i ) (1 - s_i) (1si) for all l ≤ i ≤ r l \le i \le r lir.
DreamGrid would like to know the number of ways to do so.
We use the following rules to determine whether two ways are different:
Let A = ( a 1 , a 2 , a 3 , a 4 ) A = (a_1, a_2, a_3, a_4) A=(a1,a2,a3,a4), where 1 ≤ a 1 ≤ a 2 ≤ n , 1 ≤ a 3 ≤ a 4 ≤ n 1 \le a_1 \le a_2 \le n, 1 \le a_3 \le a_4 \le n 1a1a2n,1a3a4n, be a valid operation pair denoting that DreamGrid selects integers a 1 a_1 a1 and a 2 a_2 a2 for the first operation and integers a 3 a_3 a3 and a 4 a_4 a4 for the second operation;
Let B = ( b 1 , b 2 , b 3 , b 4 ) B = (b_1, b_2, b_3, b_4) B=(b1,b2,b3,b4), where 1 ≤ b 1 ≤ b 2 ≤ n , 1 ≤ b 3 ≤ b 4 ≤ n 1 \le b_1 \le b_2 \le n, 1 \le b_3 \le b_4 \le n 1b1b2n,1b3b4n, be another valid operation pair denoting that DreamGrid selects integers b 1 b_1 b1 and b 2 b_2 b2 for the first operation and integers b 3 b_3 b3 and b 4 b_4 b4 for the second operation.
A A A and B B B are considered different, if there exists an integer k k k ( 1 ≤ k ≤ 4 1 \le k \le 4 1k4) such that a k ≠ b k a_k \ne b_k ak=bk.
Input
There are multiple test cases. The first line of the input contains an integer T T T, indicating the number of test cases. For each test case:
The first line contains an integer n n n ( 1 ≤ n ≤ 1 0 6 1 \le n \le 10^6 1n106), indicating the length of two binary sequences.
The second line contains a string s 1 s 2 … s n s_1s_2\dots s_n s1s2sn ( s i ∈ { ’0’ , ’1’ } s_i \in \{\text{'0'}, \text{'1'}\} si{’0’,’1’}) of length n n n, indicating the first binary sequence.
The third line contains a string t 1 t 2 … t n t_1t_2\dots t_n t1t2tn ( t i ∈ { ’0’ , ’1’ } t_i \in \{\text{'0'}, \text{'1'}\} ti{’0’,’1’}) of length n n n, indicating the second binary sequence.
It’s guaranteed that the sum of n n n in all test cases will not exceed 1 0 7 10^7 107.
Output
For each test case, output an integer denoting the answer.
Sample Input
3
1
1
0
2
00
11
5
01010
00111
Sample Output
0
2
6
Hint
For the second sample test case, there are two valid operation pairs: (1, 1, 2, 2) and (2, 2, 1, 1).
For the third sample test case, there are six valid operation pairs: (2, 3, 5, 5), (5, 5, 2, 3), (2, 5, 4, 4), (4, 4, 2, 5), (2, 4, 4, 5) and (4, 5, 2, 4).

题目大意:有两个01相同长度的01串,可以分别对两串执行一次操作,问有多少种方案使得两串在操作后相等。一次操作是指选取某个串的一个区间,将区间中的串按位取反。

解决方案:分情况讨论:

  1. 两个串初始是相等的。
    那么此时,两次操作的区间要相同才能使操作后的两串相等。所以问题变成满足题意得 l , r l,r l,r有多少种不同得组合。 A n s = ( n ) + ( n − 1 ) + ⋯ + ( 1 ) = ( n + 1 ) ∗ n / 2 Ans=(n)+(n-1)+\cdots +(1)=(n+1)*n/2 Ans=(n)+(n1)++(1)=(n+1)n/2
  2. 两个串初始只有一个连续的区间不同
    那么此时,操作的目的就是把这段不同的区间变为相同。由于是01串,所以连续的不同的区间操作一次就相同了。设区间 [ x , y ] [x,y] [x,y]为不相同的区间,如下图所示。
l
m
r
1
x
y
n

由于不相同的区间只能操作一次,相同的区间必须呗操作0次或两次,设操作第一个串操作区间在左边,第二个在右边,那么,有三种操作类型。一是第一次操作覆盖 [ l , x ) [l,x) [l,x),第二次操作覆盖 [ l , y ] [l,y] [l,y],其中 1 ≤ l < x 1\leq l <x 1l<x,此时有 ( x − 1 ) (x-1) (x1)种可能;二是第一次操作覆盖 [ x , r ] [x,r] [x,r],第二次操作覆盖 ( y , r ] (y,r] (y,r],其中 y < r ≤ n y<r\leq n y<rn,此时有 ( n − y + 1 − 1 ) (n-y+1-1) (ny+11)种可能;三是第一次操作覆盖 [ x , m ] [x,m] [x,m],第二次操作覆盖 ( m , y ] (m,y] (m,y]此时有 ( y − x ) (y-x) (yx)种可能。综合三种情况相加,共有 ( n − 1 ) (n-1) (n1)中可能,根据对称性,第二次操作区间在第一次左边也是 ( n − 1 ) (n-1) (n1)种可能,所以 A n s = 2 ∗ ( n − 1 ) Ans=2*(n-1) Ans=2(n1)

  1. 两个串有两个连续区间不相同。画个图数一数固定6种,和长度无关。
  2. 连续不同的区间超过2个。就两次操作机会,不可能还原的。
#include<iostream>
#include<vector>
using namespace std;

char s[1000010], t[1000010];
int T;
long long n;

int main() {
	scanf("%d", &T);
	while (T--) {
		scanf("%lld", &n);
		scanf("%s", s);
		scanf("%s", t);
		int Dif = 0, Length = 0;
		bool flag = false;
		for (int i = 0; i < n; ++i) {
			if (s[i] == t[i]) {
				if (Length != 0) {
					++Dif;
					Length = 0;
				}
			}
			else {
				++Length;
			}
		}
		if (Length != 0) {
			++Dif;
		}
		switch (Dif)
		{
		case 0: {
			printf("%lld\n", n * (n + 1) / 2);
			break;
		}
		case 1: {
			printf("%lld\n", 2 * (n - 1));
			break;
		}
		case 2: {
			puts("6");
			break;
		}
		default: {
			puts("0");
			break;
		}
		}
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值