ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[atARC110E]Shorten ABC

2020-12-10 10:06:39  阅读:256  来源: 互联网

标签:ABC int 字母 atARC110E Shorten lst ne 异或 区间


考虑令$a$、$b$和$c$分别对应1、2和3,那么每一次相当于令$x$和$y$变为$x\oplus y$(要求$x\ne y$)

根据异或的结合律,我们相当于将其划分为若干个区间求异或值

(另外还有$x\ne y$的条件,归纳可证等价于要求区间异或值不为0且区间内字母不完全相等或仅有1个字母)

为了保证每一种方案都不同,强制除了第一个以外的区间任意非空前缀异或值都不为0,否则可以把该前缀加入到上一个区间中(同时此时要保证了$x\ne y$的条件)

令$f_{i}$表示前$i$个字母对应的方案数,考虑递推转移,设$j$为第一个异或前缀和等于$i$的,那么就转移到$(i,j)$,区间修改可以用差分来维护

初始状态需要考虑一下,首先需要保证异或不为0,然后若所有字母完全相同(必然是奇数个),可以理解为最后$len-1$个字母是由下一段一个非空前缀补上来的,因此允许出现

特别的,当所有字母都相同时答案为1,需要特判

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 1000005
 4 #define mod 1000000007
 5 int n,a[N],nex[N],lst[4],f[N];
 6 char s[N];
 7 void update(int l,int r,int x){
 8     f[l]=(f[l]+x)%mod;
 9     if (r+1<n)f[r+1]=(f[r+1]+mod-x)%mod;
10 }
11 int main(){
12     scanf("%d%s",&n,s);
13     for(int i=0;i<n;i++)a[i]=s[i]-'A'+1;
14     bool flag=0;
15     for(int i=1;i<n;i++)
16         if (s[i]!=s[0])flag=1;
17     if (!flag){
18         printf("1");
19         return 0;
20     } 
21     for(int i=1;i<n;i++)a[i]^=a[i-1];
22     for(int i=0;i<4;i++)lst[i]=n;
23     for(int i=n-1;i>=0;i--){
24         nex[i]=lst[a[i]];
25         lst[a[i]]=i;
26     }
27     for(int i=0;i<n;i++)
28         if (a[i])update(i,i,1);
29     for(int i=0;i<n;i++){
30         if (i)f[i]=(f[i]+f[i-1])%mod;
31         update(i+1,nex[i]-1,f[i]);
32     }
33     printf("%d",f[n-1]);
34 } 
View Code

 

标签:ABC,int,字母,atARC110E,Shorten,lst,ne,异或,区间
来源: https://www.cnblogs.com/PYWBKTDA/p/14112042.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有