ZOJ 4060 Flippy Sequence(思維)
阿新 • • 發佈:2018-12-17
題目連結: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; }