题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4060
题目大意:有两个只包含0和1字符串,,通过将字符串1区间内的0和1反转2次(0反转为1,1反转为0),求方案数。
思路:反转的顺序不会影响最后的结果。为了方便分析,我将所有的字符串2都看作是0组成的,字符串1内的1就是需要我们反转的,分析以下情况。
(1)字符串全为1,例如:1,11,111,1111。其对应的方案数为,0,2,4,6.。ans=(n-1)*2;
(2)字符串全为0,例如:0,00,000,0000。其对应的方案数为,1,3,6,10.。ans=(n+1)*n./2;
(3)0001100类型,l表示左边0的个数,mid表示中间0的个数,r表示右边0的个数。ans=(mid-1)*2+(l+r)*2;
(4)000110011000类型,恰好两对连续的1,ans=6;
(5)000110011011,00110011011011011...类型,出现了3个及以上的连续的1,我们无法通过反转2次得到答案,ans=0;
AC代码:
#include <cstdio>
#include <queue>
#include <iostream>
using namespace std;
const int MAXN = 1e6+10;
char str1[MAXN];
char str2[MAXN];
typedef long long ll;
int main(){
//freopen("in.txt","r",stdin);
int T;scanf("%d",&T);
while(T--){
int n;scanf("%d",&n);
scanf("%s%s",str1,str2);
int flag=0;
int sameCnt=0,diffCnt=0;
queue<int> aSame,aDiff;
while(!aSame.empty()) aSame.pop();
while(!aDiff.empty()) aDiff.pop();
//flag=1表示正在计数连续相同的字符串长度
//flag=2表示正在计数连续不相同的字符串长度
for(int i=0;i<n;i++){
if(str1[i]==str2[i]){
if(flag==1){
sameCnt++;
}else if(flag==2){
aDiff.push(diffCnt);
diffCnt=0;
sameCnt=1;
flag=1;
}else{
sameCnt++;
flag=1;
}
}else{
if(flag==2){
diffCnt++;
}else if(flag==1){
aSame.push(sameCnt);
sameCnt=0;
diffCnt=1;
flag=2;
}else{
diffCnt++;
flag=2;
}
}
}
if(sameCnt) aSame.push(sameCnt);
if(diffCnt) aDiff.push(diffCnt);
ll ans=0;
if(aSame.size()==1&&aDiff.size()==0){
ans=(n+1)*n/2;
printf("%lld\n",ans);
continue;
}
if(aDiff.size()>2){
printf("0\n");
continue;
}
bool firstSame=0;
if(str1[0]==str2[0])
firstSame=1;
int l,r,mid;
if(firstSame){
if(aDiff.size()==1){
l=0;r=0;mid=0;
mid=aDiff.front();aDiff.pop();
l=aSame.front();aSame.pop();
if(aSame.empty())
ans=(mid-1)*2+l*2;
else{
r=aSame.front();aSame.pop();
ans=(mid-1)*2+(l+r)*2;
}
}else{
ans=6;
}
}else{
if(aDiff.size()==1){
l=0;r=0;mid=0;
l=aDiff.front();aDiff.pop();
if(!aSame.empty()){
mid=aSame.front();
aSame.pop();
}
ans=(l-1)*2+mid*2;
}else{
ans=6;
}
}
printf("%lld\n",ans);
}
return 0;
}