zoukankan      html  css  js  c++  java
  • AGC022E Median Replace

    题意

    给出一个长度为奇数(n)的残缺01串,问有多少种补全方法,每次将连续三个位替换为它们的中位数后,能有一种方案使它变为1
    (n le 3*10^5)

    思路

    左边表示栈顶。
    将操作简化为:将000变为0;将111变为1;删掉相邻的0110. 考虑这些操作的优先级,显然是每次有000就执行,没有就执行0110,都没有再执行 111。同类内部的顺序并不影响结果。
    现在考虑用栈维护,从左往右加入串中字符,如果加入了 1,那么栈顶是 0 便可弹掉; 如果加入了 0,由于 000 优先于其他,栈顶是 1 也暂时不操作,最后再考虑 10111 操作。这样栈的形态尝试一下,就可以得出如下列举的,只有这么几种。
    注意当(1)的个数(ge 2)时,肯定是可行的,可以等价到两个的情况。
    因为最后只要有两个(1)或者1。加起来,输出就可以了
    我的状态是这样的:-, 0,1,00,01,11,001,011,0011;

    #include <bits/stdc++.h>
    const int N=300005,mu=1000000007;
    const int tran[2][N]={{1,3,4,1,6,7,4,8,7},{2,0,5,1,2,5,4,5,7}};
    int l,dp[N][10];
    char s[N];
    void reduce(int &x){x+=x>>31&mu;}
    int main(){
    	scanf("%s",s+1);
    	int l=strlen(s+1);
    	dp[0][0]=1;
    	for (int i=1;i<=l;i++){
    		for (int j=0;j<=8;j++){
    			if (s[i]!='1') reduce(dp[i][tran[0][j]]+=dp[i-1][j]-mu);
    			if (s[i]!='0') reduce(dp[i][tran[1][j]]+=dp[i-1][j]-mu);
    		}
    	}
    	reduce(dp[l][5]+=dp[l][7]-mu);
    	reduce(dp[l][5]+=dp[l][8]-mu);
    	reduce(dp[l][5]+=dp[l][2]-mu);
    	printf("%d",dp[l][5]);
    } 
    

    后记

    我是来抄作业的。详见集训队作业题解。

  • 相关阅读:
    自定义异常处理
    遍历目录
    快速排序
    Map<String,String>转换json字符串
    Sublime Text 3破解
    替换字符串
    Moss2007迁移步骤
    Sharepoint 2010 定时提醒
    Sharepoint 2010 显示详细错误
    Sharepoint 2010 安装完Micrsoft sharepoint 2010 service pack 1后网站主页报错
  • 原文地址:https://www.cnblogs.com/flyfeather6/p/11997345.html
Copyright © 2011-2022 走看看