# ccpc 网络赛 hdu 6155(矩阵乘法 + 线段树)

题意:

给出 01 串,要么询问某个区间内不同的 01 子序列数量,要么把区间翻转。

叉姐的题解:

先考虑怎么算 \(s_1, s_2, \ldots, s_n\)的答案。

设 \(dp(i, 0/1)\) 表示考虑到 \(s_i\)

,以 \(0/1\) 结尾的串的数量。

那么 \(dp(i, 0) =dp(i - 1, 0) + dp(i - 1, 1) + 1\),\(1\)也同理。

那么假设在某个区间之前,\(dp(i, 0/1) = (x, y)\) 的话,过了这段区间,就会变成 \((ax + by + c, dx + ey + f)(ax+by+c,dx+ey+f)\) 的形式,只要用线段树维护这个线性变化就好了。


fzu 2129 子序列的个数 做过这道题的话 dp方程应该写的出来

一直在思考如何区间合并这个东西,或者区间是否具有加减性质,可以的话就可以用线段树做了,然而并不能

维护矩阵真的是涨姿势了

先列出转移矩阵把

如果\(s_i = 0\),则有

\(dp[i][0] = 1 * dp[i-1][0] + 1 * dp[i-1][1] + 1 * 1\)

\(dp[i][1] = 0 * dp[i-1][0] + 1 * dp[i-1][1] + 0 * 1\)

否则

\(dp[i][0] = 1 * dp[i-1][0] + 0 * dp[i-1][1] + 0 * 1\)

\(dp[i][1] = 1 * dp[i-1][0] + 1 * dp[i-1][1] + 1 * 1\)

初始化\(dp[0][0/1] = 0\),

初始矩阵就为

\(\begin{bmatrix}
0\\
0\\
1
\end{bmatrix}\)

如果当前为0,矩阵是这样的

\(\begin{bmatrix}
1& 1 & 1\\
0& 1 & 0\\
0& 0 & 1
\end{bmatrix}\)

否则就是这样的

\(\begin{bmatrix}
1& 0 & 0\\
0& 1 & 1\\
0& 0 & 1
\end{bmatrix}\)

假设当前字符串为01,那么最后矩阵就是

\(\begin{bmatrix}
1& 0 & 0\\
0& 1 & 1\\
0& 0 & 1
\end{bmatrix} \cdot
\begin{bmatrix}
1& 1 & 1\\
0& 1 & 0\\
0& 0 & 1
\end{bmatrix} \cdot
\begin{bmatrix}
0\\
0\\
1
\end{bmatrix} =
\begin{bmatrix}
1\\
2\\
1
\end{bmatrix}\)

通过1和0的转移矩阵容易知道区间翻转其实就是把矩阵的某些元素交换一下

然后写个线段树区间合并就好了

#include<bits/stdc++.h>
#define LL long long
#define ls rt<<1
#define rs (rt<<1|1)
using namespace std;
void read(int &x){
char c = getchar();
x = 0;
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - '0',c = getchar();
}
const int mod = 1e9 + 7;
const int N = 1e5 + 10; struct MAT{
int a[3][3];
void change(){
swap(a[0][2],a[1][2]);
swap(a[0][0],a[1][1]);
swap(a[0][1],a[1][0]);
}
}s[N << 2];
void add(int &x,int y){
x += y;
if(x >= mod) x -= mod;
}
MAT mul(MAT A,MAT B){
MAT ans;
for(int i = 0;i < 3;i++){
for(int j = 0;j < 3;j++){
ans.a[i][j] = 0;
for(int k = 0;k < 3;k++){
add(ans.a[i][j],1LL * A.a[i][k] * B.a[k][j]%mod);
}
}
}
return ans;
}
MAT mat[3];
int col[N << 2];
char S[N];
void init(){
for(int k = 0;k < 3;k++)
for(int i = 0;i < 3;i++)
for(int j = 0;j < 3;j++)
mat[k].a[i][j] = i == j?1:0;
mat[1].a[0][1] = mat[1].a[0][2] = 1;
mat[2].a[1][0] = mat[2].a[1][2] = 1;
}
void pushdown(int rt){
if(col[rt]){
col[rs] ^= 1;
col[ls] ^= 1;
s[rs].change();
s[ls].change();
col[rt] = 0;
}
}
void flip(int L,int R,int l,int r,int rt){
if(L <= l && R >= r){
col[rt] ^= 1;
s[rt].change();
return ;
}
pushdown(rt);
int m = l + r >> 1;
if(L <= m) flip(L,R,l,m,ls);
if(R > m) flip(L,R,m+1,r,rs);
s[rt] = mul(s[rs], s[ls]);
}
MAT query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r) return s[rt];
pushdown(rt);
int m = l + r >> 1;
if(L <= m && R > m) return mul(query(L,R,m+1,r,rs),query(L,R,l,m,ls));
if(L <= m) return query(L,R,l,m,ls);
if(R > m) return query(L,R,m+1,r,rs);
}
void build(int l,int r,int rt){
col[rt] = 0;
if(l == r){
s[rt] = mat[S[l] - '0' + 1];
col[rt] = 0;
return ;
}
int m = l + r>>1;
build(l,m,ls);
build(m+1,r,rs);
s[rt] = mul(s[rs], s[ls]);
}
int main(){
init();
int T,o,l,r,n,q;
read(T);
while(T--){
read(n),read(q);
scanf("%s",S+1);
build(1,n,1);
while(q--){
read(o),read(l),read(r);
if(o == 1) flip(l,r,1,n,1);
else{
MAT ans = query(l,r,1,n,1);
int tmp = (ans.a[0][2]+ans.a[1][2])%mod;
printf("%d\n",tmp);
}
}
}
return 0;
}

ccpc 网络赛 hdu 6155的更多相关文章

  1. 2019年CCPC网络赛 HDU 6703 array【权值线段树】

    题目大意:给出一个n个元素的数组A,A中所有元素都是不重复的[1,n].有两种操作:1.将pos位置的元素+1e72.查询不属于[1,r]中的最小的>=k的值.强制在线. 题解因为数组中的值唯一 ...

  2. 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

    // 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以 ...

  3. (四面体)CCPC网络赛 HDU5839 Special Tetrahedron

    CCPC网络赛 HDU5839 Special Tetrahedron 题意:n个点,选四个出来组成四面体,要符合四面体至少四条边相等,若四条边相等则剩下两条边不相邻,求个数 思路:枚举四面体上一条线 ...

  4. 2018 CCPC网络赛

    2018 CCPC网络赛 Buy and Resell 题目描述:有一种物品,在\(n\)个地点的价格为\(a_i\),现在一次经过这\(n\)个地点,在每个地点可以买一个这样的物品,也可以卖出一个物 ...

  5. hdu 6152 : Friend-Graph (2017 CCPC网络赛 1003)

    题目链接 裸的结论题.百度 Ramsey定理.刚学过之后以为在哪也不会用到23333333333,没想到今天网络赛居然出了.顺利在题面更改前A掉~~~(我觉得要不是我开机慢+编译慢+中间暂时死机,我还 ...

  6. 2018年 CCPC 网络赛 赛后总结

    历程:由于只是网络赛,所以今天就三开了.一开始的看题我看了d题,zz和jsw从头尾看起来,发现c题似乎可做,和费马大定理有关,于是和zz一起马上找如何计算勾股数的方法,比较慢的A掉了,而jsw此时看了 ...

  7. 2019杭电多校&CCPC网络赛&大一总结

    多校结束了, 网络赛结束了.发现自己还是太菜了,多校基本就是爆零和签到徘徊,第一次打这种高强度的比赛, 全英文,知识点又很广,充分暴露了自己菜的事实,发现数学还是很重要的.还是要多刷题,少玩游戏. 网 ...

  8. hdu 5833 Zhu and 772002 ccpc网络赛 高斯消元法

    传送门:hdu 5833 Zhu and 772002 题意:给n个数,每个数的素数因子不大于2000,让你从其中选则大于等于1个数相乘之后的结果为完全平方数 思路: 小于等于2000的素数一共也只有 ...

  9. 2018 CCPC网络赛 1010 hdu 6447 ( 树状数组优化dp)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6447 思路:很容易推得dp转移公式:dp[i][j] = max(dp[i][j-1],dp[i-1][j ...

随机推荐

  1. CI的子目录控制器问题

    不管是根目录还是子目录里面的文件名必须是首字母大写,否则会报404

  2. 牛客小白月赛1 I あなたの蛙が帰っています 【卡特兰数】

    链接:https://www.nowcoder.com/acm/contest/85/I题目描述 あなたの蛙が帰っています!  蛙蛙完成了一趟旅行,回家啦!但它还是没有去它心中非常想去的几个地方.总共 ...

  3. UOJ#179. 线性规划(线性规划)

    描述 提交 自定义测试 这是一道模板题. (这个题现在标程挂了..哪位哥哥愿意提供一下靠谱的标程呀?) 本题中你需要求解一个标准型线性规划: 有 nn 个实数变量 x1,x2,…,xnx1,x2,…, ...

  4. 文本处理工具-AWK

    awk简介 awk功能与sed相似,都是用来进行文本处理的.awk可以自动地搜索输入文件,并把每一个输入行切分成字段.许多工作都是自动完成的,例如读取每个输入行.字段分割. awk工作原理 awk一次 ...

  5. Intellij IDEA 查找接口实现类的快捷键

    查找接口的实现类: IDEA 风格 ctrl + alt +B 查看类或接口的继承关系: ctrl + h 1.IDEA_查找接口的实现 的快捷键 http://blog.csdn.net/u0100 ...

  6. 如何在nlp问题中定义自己的数据集

    我之前大致写了一篇在pytorch中如何自己定义数据集合,在这里如何自定义数据集 不过这个例子使用的是image,也就是图像.如果我们用到的是文本呢,处理的是NLP问题呢? 在解决这个问题的时候,我在 ...

  7. Android 拍照或相册选择照片进行显示缩放位图 Demo

    拍照后直接使用 BitmapFactory.decodeStream(...) 进行创建 Bitmap 并显示是有问题的. Bitmap 是个简单对象,它只存储实际像素数据,也就是说,即使原始照片已压 ...

  8. Codeforces 771E Bear and Rectangle Strips DP

    题意: 一个由大写字母组成的长度为\(n(n \leq 75)\)的字符串,每次操作可以交换相邻位置的两个字母,求最少操作多少次使字符串中不出现子串VK 分析: VK之外的字母具体是什么,我们并不关心 ...

  9. Java-JNA使用心得2

    自5月初第一次尝试使用Java封装调用C的dll之后,已经先后经历了3次小项目了. 上月末是最近的一次项目实际,任务来的急时间又少,还好在加班加点后还是完成了任务,并把第二次没有实现的功能给实现了(C ...

  10. 剑指Offer - 九度1355 - 扑克牌顺子

    剑指Offer - 九度1355 - 扑克牌顺子2014-01-30 23:19 题目描述: LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^). ...