zoukankan      html  css  js  c++  java
  • ARC110E

    一个由(ABC)组成的字符串,每次找相邻的两个不同的字符,将它们替换成那个和它们都不想同的字符(如(AB o C))。

    问若干次操作能够形成的字符串的方案数。

    (nle 10^6)


    类似于AGC027E。

    然而还是做不出来。

    (A,B,C)分别为(1,2,3)。可以发现每次操作之后异或和不变。

    并且可以发现如果出现了(AA)的情况,可以将它消掉(除非全部相等)。

    于是可以发现一段字符串形成一个字符的充分必要条件是:异或和相等,字符不全相等(长度为(1)的除外)。

    先把全部相等的特判掉。

    对于一个最终形成的字符串,每个字符匹配原串的一个子串。

    搞个DP,转移的时候找最小的一段。可以发现找最小的一段可以保证字符不全相等。

    统计答案的时候,如果剩下的一段异或和为(0),那么就计入答案中。因为异或和为(0),肯定有办法将后面这些消掉。

    (或者也可以这样:如果剩下一段异或和不为(0)就计入答案中。相当于最后一个字符特殊处理。如果这一段全部相等,它实际上可以和前面的互相消。因为特判了全部相同的情况,所以合法的方案总是存在的。)


    using namespace std;
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 1000005
    #define mo 1000000007
    #define ll long long
    int n;
    char str[N];
    int a[N],s[N];
    int lst[N][4];
    int f[N];
    int main(){
    	freopen("in.txt","r",stdin);
    	scanf("%d%s",&n,str+1);
    	for (int i=1;i<=n;++i){
    		a[i]=str[i]-'A'+1;
    		s[i]=s[i-1]^a[i];
    	}
    	bool same=1;
    	for (int i=1;i<n;++i)
    		same&=(a[i]==a[i+1]);
    	if (same || n==1){
    		printf("1
    ");
    		return 0;
    	}
    	lst[n+1][0]=lst[n+1][1]=lst[n+1][2]=lst[n+1][3]=n+1;
    	for (int i=n;i>=0;--i){
    		memcpy(lst[i],lst[i+1],sizeof lst[i]);
    		lst[i][s[i+1]]=i+1;
    	}
    	f[0]=1;
    	ll ans=0;
    	for (int i=0;i<n;++i)
    		for (int c=1;c<=3;++c)
    			(f[lst[i][c^s[i]]]+=f[i])%=mo;
    	for (int i=1;i<=n;++i)
    		if ((s[n]^s[i])==0)
    			ans+=f[i];
       	/*
        for (int i=0;i<n;++i)
    		if (s[n]^s[i])
    			ans+=f[i];
    	*/
    	ans%=mo;
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Uva 10494 If We Were a Child Again
    01 words & sentences BYOD
    Uva 465 Overflow
    354E
    MySQL/mariadb从删库到跑路——备份
    MySQL/mariadb知识点——日志记录(2)二进制日志
    MySQL/mariadb知识点——日志记录(1)
    MySQL/mariadb知识点——函数
    MySQL/mariadb知识点——数据库变量
    MySQL/mariadb知识点——事务Transactions
  • 原文地址:https://www.cnblogs.com/jz-597/p/14157142.html
Copyright © 2011-2022 走看看