题目链接: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. Linux学习笔记(二)——文件/目录/VIM

    文件和目录管理 及 VI编辑器的使用 文件和目录管理,刚开始学这块的时候感觉内容很多很杂,但是学完进行总结后,发现其实很有条理的而且没什么难度,只是熟练掌握这些常用的命令就行了.至于Vim编辑器,不得 ...

  2. python机器学习实战(二)

    python机器学习实战(二) 版权声明:本文为博主原创文章,转载请指明转载地址 http://www.cnblogs.com/fydeblog/p/7159775.html 前言 这篇noteboo ...

  3. 将git版本号编译进程序

    问题的提出 不管是什么版本管理工具,每一条提交记录都会有一个对应的版本号,一般是一个整数,git是一个hash字符串.不管怎样,这个版本号是唯一的,有时候我们在程序运行的时候会在日志里面输出程序的版本 ...

  4. css动画属性--轮播图效果

    通过css的动画属性实现轮播图的显示效果 代码如下: 主体部分: <div id="move"> <ul> <li><img src=&q ...

  5. Unity Shader入门教程(一)

    参考文献:http://www.360doc.com/content/13/0923/15/12282510_316492286.shtml Unity Shader是着色器,将纹理.网格信息输入,得 ...

  6. 中国(北方)大学生程序设计训练赛(第一周) (D E)

    比赛链接 D题是个二分,每次check复杂度为O(n),类似于xdu_1068,只是一个是求积,一个是求商 #include<bits/stdc++.h> using namespace ...

  7. MD5加密Demo

    package com.util; import java.security.MessageDigest; public class MD5 { public final static String ...

  8. Java之戳中痛点 - (6)避免类型自动转换,例如两个整数相除得浮点数遇坑

    先来看一个例子: package com.test; public class calculate { /** * 光速30万公里/秒 */ public static final int LIGHT ...

  9. (转)关于eclipse的TestNG的插件安装方法

    背景:最近在学习spring 4.x时候,用到了testNG的测试方法,发现需要在eclipse安装testNG插件才能够正常进行单元测试. 1 插件安装 今天在配置eclipse+selenium+ ...

  10. SQL Server事务遭遇网络异常时的处理机制浅析

    SQL Server数据库中,如果应用程序正在执行一个事务的时候突然遭遇了网络异常,例如网络掉包,网络中断等,那么这个事务会怎么样? SQL Server数据库是通过什么机制来判断处理呢? 估计很多人 ...