1. 程式人生 > >ZOJ 4060 - Flippy Sequence - [思維題][2018 ACM-ICPC Asia Qingdao Regional Problem C]

ZOJ 4060 - Flippy Sequence - [思維題][2018 ACM-ICPC Asia Qingdao Regional Problem C]

arr sequence 選擇 class ots 部分 ac代碼 while flip

題目鏈接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4060

技術分享圖片

技術分享圖片

題意:

給出兩個 $0,1$ 字符串 $S,T$,現在你有兩次對 $S$ 作區間翻轉($0 \rightarrow 1,1 \rightarrow 0$)的操作,

用四元組 $(l_1,r_1,l_2,r_2)$ 表示,代表第一次翻轉區間 $[l_1,r_1]$,第二次翻轉區間 $[l_2,r_2]$。

問你有多少個四元組可以使得 $S=T$。

題解:

把 $S$ 盡可能少地分割成若幹個子串。若某一子串和相應區間的 $T$ 一樣,記作 $B$;反之,則記作 $A$。

因此若 $A$ 的數量大於兩個,就不可能通過區間翻轉兩次使得 $S=T$,因此 $A$ 最多是兩個。

分類討論:

  1. $A$ 有 $0$ 個,即整個$S$ 可表示為 $B$,任意翻轉兩次相同區間 $[i,j]$ 即可。整個 $1 \sim |S|$ 可以有 $|S| + (|S|-1) + \cdots + 1 = \frac{|S|(|S|+1)}{2}$。
  2. $A$ 有 $1$ 個,即$S$ 可表示為 $(B)A(B)$。若兩邊都沒有 $B$,則可以將 $A$ 分成兩個部分 $[l,m],[m+1,r]$ 分別翻轉,考慮 $m$ 取值的可能有 $2 \times (|A|-1)$ 種;若兩側都有 $B$,即 $BAB$,則應在前面那種基礎上,再算上,在某一側的 $B$ 中挑選一個左端點,再以 $A$ 的右端點為區間右端點,這樣一來有 $2 \times |B|$ 種選擇。兩者加起來即 $2 \times (|A|-1+|B|) = 2 \times (|S|-1)$。
  3. $A$ 有 $2$ 個,即$S$ 可表示為 $(B)ABA(B)$。只能有三種翻法:①ABA,B;②AB,BA;③A,A。因此即 $2 \times 3 = 6$ 種可能性。

AC代碼:

#include<bits/stdc++.h>
using namespace std;
int n;
string s,t;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n>>s>>t;
        
int cnt=0; for(int i=0;i<n;i++) { if((i==0 || s[i-1]==t[i-1]) && s[i]!=t[i]) cnt++; } if(cnt>2) cout<<"0\n"; else if(cnt==2) cout<<"6\n"; else if(cnt==1) cout<<(2*n-2)<<\n; else cout<<((long long)n*(n+1)/2)<<\n; } }

ZOJ 4060 - Flippy Sequence - [思維題][2018 ACM-ICPC Asia Qingdao Regional Problem C]