2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6155 Subsequence Count 矩阵快速幂
题目链接: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 矩阵快速幂的更多相关文章
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6152 Friend-Graph(暴力搜索)
题目传送:http://acm.hdu.edu.cn/showproblem.php?pid=6152 Problem Description It is well known that small ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6150 Vertex Cover 二分图,构造
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6150 题意:"最小点覆盖集"是个NP完全问题 有一个近似算法是说—每次选取度数最大 ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha's staff 思维
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6154 题意:在笛卡尔坐标系下,画一个面积至少为 n 的简单多边形,每次只能画一条边或者一个格子的对角 ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6152 Friend-Graph 暴暴暴暴力
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6152 题意:判定一个无向图是否有三个点的团或者三个点的独立集. 解法:Ramsey theorem,n ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6153 A Secret KMP,思维
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6153 题意:给了串s和t,要求每个t的后缀在在s中的出现次数,然后每个次数乘上对应长度求和. 解法:关 ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6156 数位DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6156 题意:如题. 解法:数位DP,暴力枚举进制之后,就转化成了求L,R区间的回文数的个数,这个直接做 ...
- 2017中国大学生程序设计竞赛 - 网络选拔赛 HDU 6154 CaoHaha's staff(几何找规律)
Problem Description "You shall not pass!"After shouted out that,the Force Staff appered in ...
- 【2017中国大学生程序设计竞赛 - 网络选拔赛 && hdu 6154】CaoHaha's staff
[链接]点击打开链接 [题意] 给你一个面积,让你求围成这个面积最少需要几条边,其中边的连线只能是在坐标轴上边长为1的的线或者是两个边长为1 的线的对角线. [题解] 找规律题 考虑s[i]表示i条边 ...
- 【2017中国大学生程序设计竞赛 - 网络选拔赛 hdu 6150】Vertex Cover
[链接]点击打开链接 [题意] 有人写了一个最小点覆盖的贪心算法,然后,让你去hack它. 并且,要求这个算法得到的错误答案,是正确答案的三倍. 让你任意输出hack数据,点数<=500 [题解 ...
随机推荐
- windows 10 下使用 binwalk
刚接触CTF没什么经验,菜鸟一只很多题不会做,就在网上看大佬写的Write up.发现经常会用到一个小工具--binwalk.binwalk在kali系统里是一个自带的工具,但windows可没有.之 ...
- [CF161D]Distance in Tree-树状dp
Problem Distance in tree 题目大意 给出一棵树,求这棵树上有多少个最短距离为k的点对. Solution 这个题目可以用点分治来做,然而我到现在还是没有学会点分治,所以只好用树 ...
- 了解Java基础原理
Java 是1995年SUN公司推出的一门高级编程语言,是面向互联网的语言,WEB应用程序首选的语言(安卓底层,大数据hadoop框架用java编写,Spark用Scala编写,Scala用java写 ...
- WPF转换器之通用转换器
WPF中的转换器是一个非常好的数据类型转换解决方案,实用和强大, 它的作用是将源数据转换为WPF自身需要的类型,对数据实体没有侵略性,会在项目工程中频繁使用.所以掌握转换器是WPF开发的必备技能. 我 ...
- 【Django】学习资料
一.基础 http://www.ibm.com/developerworks/cn/linux/l-django/ 安装.数据库连接.url路由转发 http://djangobook.py3k.cn ...
- 【Django】request 处理流程(转)
Django 和其他 Web 框架的 HTTP 处理的流程大致相同,Django 处理一个 Request 的过程是首先通过中间件,然后再通过默认的 URL 方式进行的.我们可以在 Middlewar ...
- LeetCode题解 343.Integer Break
题目:Given a positive integer n, break it into the sum of at least two positive integers and maximize ...
- idea项目上传到码云
从idea托管项目到码云相对其他软件来说是非常简单的,只要第一次下载好git插件,然后托管如下: 1. 2. 3.登陆成功后,默认会将项目所有项全选,托管成功后右下角会显示 4.当以后项目有变化时再如 ...
- Python中的re模块--正则表达式
Python中的re模块--正则表达式 使用match从字符串开头匹配 以匹配国内手机号为例,通常手机号为11位,以1开头.大概是这样13509094747,(这个号码是我随便写的,请不要拨打),我们 ...
- sort排序错乱问题
对于sort排序 之前就遇到过这种问题 不过没有在意 今天遇到 就找了一下原理 在这种sort排序中可以看到排序几乎没有什么问题 就是5比较特殊 会在20是的后面 ~ sort()方法开始的时候会 ...