题目链接: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. Django 踩过的坑(一)

    平台:win10 工具:cmd python3 刚刚学习Django搭建环境,网站还木有发布,就直接来了个大麻烦. 一切按着<Django 学习笔记(二)>这篇文章来的,在最后cmd运行服 ...

  2. 构建自己的Tomcat镜像

    在很多情况下,我们会不满足于官方提供的Tomcat镜像.比如官方镜像的时区为UTC时间,并不是北京时间:再比如在特定硬件环境下,jdk的随机数生成器初始化过慢问题.此时,我们就会考虑构建自己的Tomc ...

  3. Java条形码/二维码生成和解析

    注意-本类依赖jar包文件:core.jar和zxing-javase.jar 下载jar文件,到本博客文件栏目下载. import com.google.zxing.BarcodeFormat; i ...

  4. JavaScript一个google地图获取

    <script type="text/javascript"> /** * 返回一个新创建的<img>元素,该元素用于在获取到地理位置信息后,显示一张Goo ...

  5. iOS实现Android中Gone的功能

    实现隐藏view但不占位置的需求是很常见的(Android里的view.GONE),可iOS里并没有这玩意,只有hidden.于是自己写了一个一般情况下用的category,特殊情况就得看情况做了.其 ...

  6. AllPairs运用遇到的问题及解决办法分享

    前些天用AllPairs自动生成了交互式测试用例,中间遇到的问题困扰了一天,最后解决了.现在分享下解决过程 首先,D\AllPairs是我的ALLPairs安装目录,C盘桌面test.txt是我写的测 ...

  7. Android - DrawerLayout

    Android DrawerLayout 的使用 Android L Android Studio 1.4 从主视图左侧能抽出一个导航栏,效果图:  点击后弹出新界面:  新界面也可以抽出左侧导航栏 ...

  8. MySQL系列(一)--基础知识大总结

    MySQL系列(一)---基础知识大总结 前言:本文主要为mysql基础知识的大总结,mysql的基础知识很多,这里只是作为简单的介绍,但是具体的细节还是需要自行搜索.当然本文还有很多遗漏的地方,后续 ...

  9. GIT - 代码管理工具之命令集

    GIT 是一个快速.可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问.它会把你的每次提交的文件的全部内容都会记录下来. GIT特点 速度 简单的设计 对非线性开发 ...

  10. mysql浅龟定

    一,尽量不字啊数据库做运算 1,尽量不再数据库做运算, 2,将复杂运算移动到cpu 3,尽可能简单应用mysql 二,控制表数据量 1,纯 int不超过1000w 2,含char不超过500w 3,建 ...