1. 程式人生 > 實用技巧 >Codeforces Global Round 4 B. WOW Factor (字首和,數學)

Codeforces Global Round 4 B. WOW Factor (字首和,數學)

  • 題意:找出序列中有多少子序列是\(wow\),但是\(w\)只能用\(vv\)來表示.

  • 題解:我們分別記錄連續的\(v\)\(o\)的個數,用\(v1\)\(v2\)存,這裡要注意前導\(o\)不能要,觀察一下寫出答案公式:\(ans=v1[i]*(v2[i]*(v1[i+1]+...+v1[k])+v2[i+1]*(v1[i+2]+...+v1[k])+...+v2[k-1]*v[k])+v1[i+1]*(...)+...+v1[k-1]*v2[k-1]*v1[k]\),很顯然我們是不能直接算的,但是發現這個公式裡面有很多連續的線性和,所以我們可以用字首和來進行復雜度的優化,將其降到\(O(n)\)

    .

  • 程式碼:

    string s;
    vector<ll> v1,v2;
    ll cnt1,cnt2;
    ll pre1[N],pre[N];
    
    int main() {
        ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
        cin>>s;
        bool flag=false;
        for(int i=0;i<(int)s.size();++i){
        	if(s[i]=='v'){
        		cnt1++;
        		if(cnt2 && flag){
        			v2.pb(cnt2);
        			cnt2=0;
        		}
        		if(!flag) cnt2=0;
        		flag=true;
        	}
        	else{
        		cnt2++;
        		if(cnt1){
        			v1.pb(cnt1);
        			cnt1=0;
        		}
        	}
        }	
        if(cnt1) v1.pb(cnt1);
    
        int len1=(int) v1.size();
        int len2=(int) v2.size();
        for(int i=len1-1;i>=0;--i){
        	pre1[i]=pre1[i+1]+v1[i]-1;   //先對v1求字首和.
        }	
        for(int i=len2-1;i>=0;--i){
        	pre[i]=pre[i+1]+v2[i]*pre1[i+1];  //求出v2[i]*(v1[i+1]+...+v1[k])的字首和pre[i]<-這裡(...)的就是我們上一步求的字首和pre1[i+1].
        }
        ll ans=0;
        for(int i=0;i<len1;++i){
        	ans+=(v1[i]-1)*pre[i];
        }
        cout<<ans<<endl;
    	
        return 0;
    }