1. 程式人生 > >2018年ACM-ICPC亞洲青島區域競賽

2018年ACM-ICPC亞洲青島區域競賽

Time Limit: 1 Second      Memory Limit: 65536 KB

Problem solving report:

Description: 給出A和B兩個01串,通過兩次反轉使得A串變成B串,問有多少種方法(這個反轉指的是連續的一段區間)

Problem solving: 分類討論:

我們可以先定義一個數組利用異或來判斷兩個串是否相等,例如串A:010100和串B:001110,異或後得串C:011010,我們只要把這個串C變成全為0(即000000),即可判定兩串相等。

首先我們可以判斷有幾個連續區間不相等時(即串C有幾個連續為1的),例如:011010就有兩個連續為1的.

1. 當兩個串相等的時候(即串C全為0),則我們可以在串C上隨意找到一個區間,對這個區間進行兩次反轉後還是0串,這樣的區間共有n*(n+1)/2個,則共有n*(n+1)/2種方法.

2. 當兩個串有1個連續區間不相等(即串C有1個連續為1的),例如:000111、011100、111000.我們可以把這種有1個連續為1的串看成x(0個數)y(1的個數)z(0個數),假設串C為:011100,則(011100:132).當我們把前面的0也改變的時候共有x種方法:我們可以改變1~4和1~1即(1,4,1,1).當我們把後面的0也改變的時候共有z種方法:我們可以改變2~5和5~5即(2,5,5,5),也可以改變2~6和5~6即(2,6,5,6),即可把串C變為0串.當我們不改變0的時候共有y-1種方法:改變2~2和3~4即(2,2,3,4),改變2~3和4~4即(2,3,4,4),就是把y個1分成兩個區間共有y-1種方法,上述操作換一下順序也是可以的,即改變1~4和1~1和改變1~1和1~4是一樣的,但這是兩種操作,故是該串C變為0串共有(x+y-1+z)*2=(n-1)*2=10種方法.

3. 當兩個串有2個連續區間不相等(即串C有2個連續為1的),例如:010111、010100、111010.我們很容易發現兩次操作只要第一次改變一個區間,第二次改變另一個區間就可以把這個串變成0串.當我們單獨的操作為1的,不改變0,則有1種方法.當我們兩次操作都把中間的0也改變的時候,又有1種方法.當我們第一次操作把兩個區間一次全部反轉,第二次操作再把中間的0改變過來,又是1種方法.類似於上面,上述操作換一下順序也是可以的,故這種型別的共有3*2=6種方法.

4. 當兩個串有3個及以上連續區間不相等(即串C有3個及以上連續為1的),例如:010101、1010101、101010.我們很容易發現,我們沒有任何方法使它變成0串,故有0種方法.

綜上:

兩個串一樣: 共有n*(n+1)/2種方法; 一個區間不一樣: 共有(n-1)*2種方法; 兩個區間不一樣: 6種方法; 三個及三個以上: 0種方法.

#include <stdio.h>
#define N 1000020
int c[N];
char a[N], b[N];
int main()
{
	int t, n, temp;
	scanf("%d", &t);
	while (t--)
	{
		temp = 0;
		scanf("%d", &n);
		scanf("%s%s", a, b);
		for (int i = 0; i < n; i++)
			c[i] = (a[i] - '0') ^ (b[i] - '0');
		if (c[0])
			temp++;
		for (int i = 1; i < n && temp <= 2; i++)
			if (c[i] && !c[i - 1])
				temp++;
		if (!temp)
			printf("%d\n", n * (n + 1) / 2);
		else if(temp == 1)
			printf("%d\n", (n - 1) * 2);
		else if (temp == 2)
			printf("6\n");
		else printf("0\n");
	}
	return 0;
}