题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6155

题意:

题解来自:http://www.cnblogs.com/iRedBean/p/7398272.html

先考虑dp求01串的不同子序列的个数。

dp[i][j]表示用前i个字符组成的以j为结尾的01串个数。

如果第i个字符为0,则dp[i][0] = dp[i-1][1] + dp[i-1][0] + 1,dp[i][1] = dp[i-1][1]

如果第i个字符为1,则dp[i][1] = dp[i-1][1] + dp[i-1][0] + 1,dp[i][0] = dp[i-1][0]

显然这是线性递推,我们考虑如何用矩阵表示这种递推关系。

下面分别对应加入一个字符0或1时表示递推关系的矩阵。

然后用线段树维护每个区间的矩阵乘积就可以解决查询操作了。

对于修改操作,我们给区间维护一个flip标记,表示该区间是否要翻转,用线段树区间更新的方法去更新flip标记就好了。

将一个区间翻转后,它对应矩阵也要发生改变,这里我们只要将矩阵的第一列与第二列交换后再将第一行与第二行交换就好了。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+6;
const int mod = 1e9+7;
typedef long long LL;
struct Matrix{
LL maze[3][3];
friend Matrix operator*(const Matrix& a, const Matrix& b){
Matrix c;
for(int i=0; i<3; i++){
for(int j=0; j<3; j++){
c.maze[i][j]=0;
for(int k=0; k<3; k++){
c.maze[i][j]+=a.maze[i][k]*b.maze[k][j];
c.maze[i][j]%=mod;
}
}
}
return c;
}
};
const Matrix m[2]={{1,0,0,1,1,0,1,0,1},{1,1,0,0,1,0,0,1,1}};
Matrix T[maxn<<2];
bool flip[maxn<<2];
char s[maxn];
void build(int l, int r, int rt){
flip[rt] = 0;
if(l == r){
T[rt] = m[s[l]-'0'];
return;
}
int mid = (l+r)>>1;
build(l, mid, rt*2);
build(mid+1, r, rt*2+1);
T[rt] = T[rt*2]*T[rt*2+1];
}
void Flip(Matrix &mat){
swap(mat.maze[0][0],mat.maze[0][1]);
swap(mat.maze[1][0],mat.maze[1][1]);
swap(mat.maze[2][0],mat.maze[2][1]);
swap(mat.maze[0][0],mat.maze[1][0]);
swap(mat.maze[0][1],mat.maze[1][1]);
swap(mat.maze[0][2],mat.maze[1][2]);
}
void pushdown(int rt){
if(flip[rt]){
flip[rt*2]^=flip[rt];
flip[rt*2+1]^=flip[rt];
Flip(T[rt*2]);
Flip(T[rt*2+1]);
flip[rt]=false;
}
}
void update(int L, int R, int l, int r, int rt){
if(L<=l&&r<=R){
flip[rt]^=1;
Flip(T[rt]);
return;
}
pushdown(rt);
int mid=(l+r)/2;
if(R<=mid) update(L,R,l,mid,rt*2);
else if(L>mid) update(L,R,mid+1,r,rt*2+1);
else{
update(L,mid,l,mid,rt*2);
update(mid+1,R,mid+1,r,rt*2+1);
}
T[rt]=T[rt*2]*T[rt*2+1];
}
Matrix query(int L, int R, int l, int r, int rt){
if(L<=l&&r<=R){
return T[rt];
}
pushdown(rt);
int mid=(l+r)/2;
if(R<=mid) return query(L,R,l,mid,rt*2);
else if(L>mid) return query(L,R,mid+1,r,rt*2+1);
else return query(L,mid,l,mid,rt*2)*query(mid+1,R,mid+1,r,rt*2+1);
}
int main()
{
int T,n,q;
scanf("%d", &T);
while(T--)
{
scanf("%d%d",&n,&q);
scanf("%s",s+1);
build(1,n,1);
while(q--)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(op==1) update(l,r,1,n,1);
else{
Matrix ret = query(l,r,1,n,1);
printf("%lld\n", (ret.maze[2][0]+ret.maze[2][1])%mod);
}
}
}
return 0;
}

2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6155 Subsequence Count 矩阵快速幂的更多相关文章

  1. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6152 Friend-Graph(暴力搜索)

    题目传送:http://acm.hdu.edu.cn/showproblem.php?pid=6152 Problem Description It is well known that small ...

  2. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6150 Vertex Cover 二分图,构造

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6150 题意:"最小点覆盖集"是个NP完全问题 有一个近似算法是说—每次选取度数最大 ...

  3. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha's staff 思维

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6154 题意:在笛卡尔坐标系下,画一个面积至少为  n 的简单多边形,每次只能画一条边或者一个格子的对角 ...

  4. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6152 Friend-Graph 暴暴暴暴力

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6152 题意:判定一个无向图是否有三个点的团或者三个点的独立集. 解法:Ramsey theorem,n ...

  5. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6153 A Secret KMP,思维

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意:给了串s和t,要求每个t的后缀在在s中的出现次数,然后每个次数乘上对应长度求和. 解法:关 ...

  6. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6156 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6156 题意:如题. 解法:数位DP,暴力枚举进制之后,就转化成了求L,R区间的回文数的个数,这个直接做 ...

  7. 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha's staff(几何找规律)

    Problem Description "You shall not pass!"After shouted out that,the Force Staff appered in ...

  8. 【2017中国大学生程序设计竞赛 - 网络选拔赛 && hdu 6154】CaoHaha's staff

    [链接]点击打开链接 [题意] 给你一个面积,让你求围成这个面积最少需要几条边,其中边的连线只能是在坐标轴上边长为1的的线或者是两个边长为1 的线的对角线. [题解] 找规律题 考虑s[i]表示i条边 ...

  9. 【2017中国大学生程序设计竞赛 - 网络选拔赛 hdu 6150】Vertex Cover

    [链接]点击打开链接 [题意] 有人写了一个最小点覆盖的贪心算法,然后,让你去hack它. 并且,要求这个算法得到的错误答案,是正确答案的三倍. 让你任意输出hack数据,点数<=500 [题解 ...

随机推荐

  1. Tween 若干年后我尽然还要学数学 曲线到底是什么鬼啊

    var Tween = { linear: function (t, b, c, d){ //匀速 return c*t/d + b; }, easeIn: function(t, b, c, d){ ...

  2. VB6之摄像头控制

    参考文献:http://www.cnblogs.com/xidongs/archive////.html 直接上代码: 'code by lichmama from cnblogs.com '@vb6 ...

  3. voa 2015 / 4 / 19

      potentially – adv. capable of becoming real, a possibility tackle – v. to deal with a difficult pr ...

  4. mysql数据库左联的使用(一张数据库表关联到另外一张数据库表)

    左联的数据库表,然后显示的在页面显示的jsp里面改一下代理种类ID的name,这样在页面上显示的不是id了,而是变成你修改了以后相对于的name了

  5. Tkinter开发第一个桌面程序HelloWorld

    在Python3中是tkinter,Python2中是Tkinter Tkinter是Python 官方承认的标准 GUI 方案(de-facto standard),因为是Python自带安装,决定 ...

  6. Java虚拟机:如何判定哪些对象可回收?

    版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在堆内存中存放着Java程序中几乎所有的对象实例,堆内存的容量是有限的,Java虚拟机会对堆内存进行管理,回收已经"死去&quo ...

  7. Qt中使用CEF(Windows下)

    最近项目中要在Qt中使用CEF(Chromium Embedded Framework),在这里总结下其中的几个要点. 下载合适的CEF版本 关于CEF的简介我们这里就不做介绍了,下载CEF可以有2种 ...

  8. [luogu P1967][NOIp2013] 货车运输

    题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...

  9. Ansible 运维自动化 ( 配置管理工具 )

    背景 出差背景,要搞项目的自动化部署.因为只直接对接生产分发,机器又非常多,这样以往使用的bat只能作为应急方案了,还是得考虑使用专业化的工具来做这个事情! 当下有许多的运维自动化工具( 配置管理 ) ...

  10. (转)Linux服务器安装配置tomcat

    这里首先说明下,Linux下的Tomcat没有32位和64位的区分. tomcat是分windows版本与linux版本的,windows版本一般以exe或者zip格式:linux版本一般以tar.g ...