zoukankan      html  css  js  c++  java
  • C. The Fair Nut and String 递推分段形dp

    C. The Fair Nut and String 递推分段形dp

    题意

    给出一个字符串选择一个序列({p_1,p_2...p_k})使得
    对于任意一个(p_i) , (s[p_i]==a)
    对于任意一个(p_{i}<j<p_{i+1})来说 ({exists}s[p_j]==b)

    思路

    所以我们可以得知 我们需要选择一系列a 使得a和a之间只能是b
    那么我们就可以对a进行分段处理
    例如aaaabaaaa 右面与前面组合 只能选择后面一大串a的前缀和前面一大串a的后缀组合才合法
    也就是一共有 num[1]*num[2]中组合 其中num[i] 表示第i段有多少个a
    而如果多段组合的话 第三段既可以和第二段组合 也可以和第二段+第一段组合
    第二段+第一段就是 在算第三段之前的合法选择数,而第三段和第二段 同第一段和第二段的算法相同
    所以递推求解即可 而分段的时候如果字母不是b 直接忽略就行了(因为只是({exists}s[p_j]==b))所以不会干扰a和a的组合可以忽略,相当于归到一段a中但是这一段a的数量不变
    ps:记得开long long

    #include<bits/stdc++.h>
    #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
    #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
    #define F first 
    #define S second
    #define pii pair<int ,int >
    #define mkp make_pair
    #define pb push_back
    #define arr(zzz) array<ll,zzz>
    using namespace std;
    typedef long long ll;
    const int maxn=3e5+5;
    int n,m,y;
    const int mod=1e9+7;
    char s[maxn];
    int main(){
    	
    	scanf("%s",s+1);
    	int len=strlen(s+1);
    	long long ans=0;
    	for(int i=1;i<=len;i++){
    		if(s[i]=='a')ans++;
    	}
    	ll flag=0;
    	ll tmp=0;
    	int cnt=0;
    	ll x=0;
    	ll fixsum=0;
    	ll lastsum=0;
    	int ok=0;
    	for(int i=1;i<=len;i++){
    		if(s[i]=='a'){
    			flag++;
    		}
    		else if(s[i]=='b'){
    			if(flag){
    				cnt++;
    			tmp+=flag*fixsum;
    			tmp%=mod;
    			//ll zzzz=lastsum;
    			//lastsum=tmp;
    			tmp+=lastsum*flag;
    			tmp%=mod;
    			lastsum=tmp;
    			fixsum+=flag;
    			fixsum%=mod;
    			flag=0;
    			}
    		}
    		if(s[i]=='b')ok=0;
    		else if(s[i]=='a')ok=1;
    	}
    	if(ok){
    				cnt++;
    			tmp+=flag*fixsum;
    			tmp%=mod;
    			//ll zzzz=lastsum;
    			//lastsum=tmp;
    			tmp+=lastsum*flag;
    			tmp%=mod;
    			lastsum=tmp;
    			fixsum+=flag;
    			fixsum%=mod;
    			flag=0;
    	}
    	if(cnt>=2)ans+=tmp;
    	ans%=mod;
    	cout<<ans<<endl;
    	return 0;
    }
    
  • 相关阅读:
    C++的一道变态题
    关于"短信处理"模式的一段讨论
    Fire Balls 10——音效的添加
    Stealth——01场景的基本搭建以及基础逻辑
    Fire Balls 09——砖块的淡出,消失以及砖塔的下落
    Fire Balls 08——子弹的消失,当子弹击中自身时不可发射子弹
    Unity进阶:PlayMaker
    Fire Balls 07——子弹的命中及后续效果
    Fire Balls 06——坦克和子弹的制作以及炮台发射子弹
    Fire Balls 05——砖塔的创建,动态上升以及旋转
  • 原文地址:https://www.cnblogs.com/ttttttttrx/p/10800062.html
Copyright © 2011-2022 走看看