问题 C: 二进制
时间限制: 1 Sec
内存限制: 128 MB
提交: 8
解决: 2
[ 提交] [ 状态] [ 讨论版] [命题人:
]
题目描述
pupil发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是3的倍数。他想研究对于二进制,是否也有类似的性质。于是他生成了一个长为n的二进制串,希望你对于这个二进制串的一个子区间,能求出其有多少位置不同的连续子串,满足在重新排列后(可包含前导0)是一个3的倍数。两个位置不同的子区间指开始位置不同或结束位置不同。由于他想尝试尽量多的情况,他有时会修改串中的一个位置,并且会进行多次询问。
输入
输入第一行包含一个正整数n,表示二进制数的长度。
之后一行n个空格隔开的整数,保证均是0或1,表示该二进制串。
之后一行一个整数m,表示询问和修改的总次数。
之后m行每行为1 i,表示pupil修改了串的第i个位置(0变成1或1变成0),或2 l r,表示pupil询问的子区间是[l,r]。
串的下标从1开始。
输出
对于每次询问,输出一行一个整数表示对应该询问的结果。
样例输入
4
1 0 1 0
3
2 1 3
1 3
2 3 4
样例输出
2
3
提示
对于第一个询问,区间[2,2]只有数字0,是3的倍数,区间[1,3]可以重排成011(2)=3(10),是3的倍数,其他区间均不能重排成3的倍数。
对于第二个询问,全部三个区间均能重排成3的倍数(注意00也是合法的)。
对于20%的数据,1≤n,m≤100;
对于50%的数据,1≤n,m≤5000;
对于100%的数据,1≤n,m≤100000,l≤r。
Solution:
设cnt0,cnt1分别为[l,r]区间内的1和0的个数,易得:
1. if cnt1==1 => 不可整除3
2. if cnt1&1 and cnt0<2 => 不可整除3
简单证明上述结论:
显然结论1是成立的(1<
先考虑这种情况,将一个二进制数将其两位两位拆分并求和得到sum,显然如果 sum%3==0 ,则该二进制数的十进制一定可以整除3。
如:111010001=>(01,11,01,00,01),sum=1+3+1+0+1=6。
那么,对于奇数个1,从中挑出cnt1-3个“1”两两组合,确保对sum%3的结果无贡献后,再看剩下的3个“1”的情况:
①、sum(111)=4 无法整除。【区间内无0】
②、sum(1101)=4,sum(1011)=5 无法整除。【区间内只含有一个0】
③、sum(10101)=3 可整除。【区间内至少含有两个0】
综上:
我们用线段树去维护上述两种不合法情况,再用【总数-不合法数=合法数】来得到答案。
其中,dl/dr[2][2] 代表经过左右节点后:cnt0=0/1,cnt1&1?1:0。
fl/fr[3] 代表经过左右节点后:满足(cnt1==1 and cnt0==0/1)的方案数。
L/R表示经过左右节点后,连续0的长度。
代码:
1 #include
2 #include <string>
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
View Code