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 [题解 ...
随机推荐
- 如何用webpack实现自动化的前端构建工作流
什么是自动化的前端构建流? 1. 自动补全css私有前缀,自动转化less\sass为css,自动转化es6\vue\jsx语法为js,自动打包小图片为base64以减少http请求,自动给js,cs ...
- 【Python3之多线程】
一.threading模块 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性. 1.开启线程的两种方式(同Process) 方法一 from thr ...
- PostMessage,模拟键盘输入
for i := 0 to length(tel) do begin //SendMessage(cHwnd,WM_KEYDOWN,Integer(tel[ ...
- Tkinter开发第一个桌面程序HelloWorld
在Python3中是tkinter,Python2中是Tkinter Tkinter是Python 官方承认的标准 GUI 方案(de-facto standard),因为是Python自带安装,决定 ...
- OCP 11G 实验环境安装文档 ( RedHat5.5 + Oracle11g )
RedHat5.5 linux下Oracle11g软件安装 一.配置虚拟机 为了创建和配置虚拟机,你需要添加硬件设备如磁盘和cpu,在你开始安装之前,创建一个windows目录作为存放虚拟机的目录 目 ...
- ubuntu14.04_caffe2安装
今天F8开发者大会上,Facebook正式发布Caffe2.经过一天的折腾,终于在ubuntu14.04上成功配置caffe2,现将经验分享如下: 1.ubuntu14.04系统下caffe2所需依赖 ...
- Jenkins2 实现持续交付初次演练(MultiJob,Pipeline,Blue Ocean)
背景 项目需要用到自动部署,但可获取外网的节点机器只有一台,那只能同过主节点机器进行构建完成然后分发至对应服务器进行启动更新. 目前已尝试过三种方式: 1.Pipeline-Trigger param ...
- Hybris安装和各个Extention简单介绍
前言:突然想好好梳理一下这几个月所学的内容了,顺便让自己的知识有一个系统的框架. 一. 安装JDK 请安装最新的Oracle JDK 8.0版(从Oracle官网下载). 二.开发工具建议使用 In ...
- Ant Design UI组件
Ant Design 是面向中台的 UI 设计语言. http://ant.design/
- HDU6043 KazaQ's Socks
Problem Description KazaQ wears socks everyday. At the beginning, he has n pairs of socks numbered f ...