noip模拟赛多校第八场 T4 不要翻墙 (矩阵乘法优化DP, 动态DP)

题目描述

在这里插入图片描述

简要题意:太长了,就不总结了,自己看吧。

分析

        我们首先考虑 m = 1 m = 1 m=1 的情况:
         T > 0 T > 0 T>0 时,显然我们可以 O ( n ) O(n) O(n) 的维护一个 前缀积前缀积的逆元,然后每次询问 O ( 1 ) O(1) O(1) 得到答案就好了。时间复杂度 O ( n ) O(n) O(n)
        T = 0 T = 0 T=0 时,我们需要在 O ( n ) O(n) O(n) 的复杂度算出答案。设 d p i dp_i dpi 表示终点是 i i i 的所有路径的答案,那么转移就是 d p i = d p i − 1 × a i + a i dp_i = dp_{i - 1} \times a_i + a_i dpi=dpi1×ai+ai。然后把所有 d p i dp_i dpi 累加起来就好了。

        然后我们考虑 m = 2 m = 2 m=2 的情况:

        因为有一条限制是路径上的位置 列数要单调不降,所以我们 以列为阶段 dp,设 d p i , 0 / 1 dp_{i, 0/1} dpi,0/1 表示当起点固定,从起点到第 0 / 1 0/1 0/1 行,第 i i i 列的所有合法路径的答案。但是发现在同一列的时候可以向上走,这样的话同一列就能相互转移了。好像有后效性?

        我们考虑怎样把这个后效性去掉。我们直接列出 d p i , j dp_{i, j} dpi,j 关于 第 i − 1 i - 1 i1 列的转移:

        d p i , j = d p i − 1 , j ∗ a j , i + d p i − 1 , 1 − j ∗ a 1 − j , i ∗ a j , i dp_{i, j} = dp_{i - 1, j} * a_{j, i} + dp_{i - 1, 1 - j} * a_{1 - j, i} * a_{j, i} dpi,j=dpi1,jaj,i+dpi1,1ja1j,iaj,i

        相当于我们是以 i − 1 i - 1 i1 列是由哪个位置到达第 i i i 划分,这样能够保证不重不漏,并且没有后效性。

        有了这个式子,我们可以在 O ( T n ) O(Tn) O(Tn) 的复杂度内处理 T > 0 T > 0 T>0 的答案。在 O ( n 2 ) O(n^2) O(n2) 的复杂度内处理出 T = 0 T = 0 T=0 的答案。并且当 T ≤ 1 0 5 , n ≤ 5000 T \leq 10^5,n \leq 5000 T105n5000 时。我们可以预处理出来任意两点作为起点和终点的答案。时间复杂度是 O ( n 2 ) O(n^2) O(n2)

       这样我们就有了 45 p t s 45pts 45pts

       接下来我们思考正解:

       不难发现,转移式满足 矩阵乘法 的运算规则,并且需要加速阶段,每一阶段状态数很少,符合矩阵乘法优化DP的特点。

       设 [ d p 0 d p 1 ] \begin{bmatrix}dp_0 & dp_1 \end{bmatrix} [dp0dp1] 表示到某一列第 0 / 1 0 / 1 0/1 行的 dp 值。那么对于第 i i i 列而言,可以构建一下伴随矩阵:

[ a 0 , i a 0 , i × a 1 , i a 1 , i × a 0 , i a 1 , i ] \begin{bmatrix} a_{0,i} & a_{0, i} \times a_{1, i}\\ a_{1, i} \times a_{0, i} & a_{1, i} \end{bmatrix} [a0,ia1,i×a0,ia0,i×a1,ia1,i]

       能够发现不同列的伴随矩阵是不同的,我们使用线段树维护区间矩阵的乘积即可。

       那么 T > 0 T > 0 T>0 的情况就可以在 O ( T l o g 2 n ) O(Tlog_2n) O(Tlog2n) 的复杂度内解决。

       至于 T = 0 T = 0 T=0 的情况,我们可以在矩阵中多维护一维 S S S 表示固定一个起点时,从起点到当前列上一列的所有路径的和。伴随矩阵变成一个下列一个 3 × 3 3 \times 3 3×3 的矩阵:

[ a 0 , i a 0 , i × a 1 , i 1 a 1 , i × a 0 , i a 1 , i 1 0 0 1 ] \begin{bmatrix} a_{0,i} & a_{0, i} \times a_{1, i} & 1\\ a_{1, i} \times a_{0, i} & a_{1, i} & 1\\ 0 & 0 & 1 \end{bmatrix} a0,ia1,i×a0,i0a0,i×a1,ia1,i0111

       然后每次枚举起点算出答案并累加就好了。时间复杂度 O ( n l o g 2 n ) O(nlog_2n) O(nlog2n)

CODE:

#include<bits/stdc++.h>// 动态DP 
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
const LL mod = 1e9 + 7;
inline int read(){int x = 0, f = 1; char c = getchar();while(!isdigit(c)){if(c == '-') f = -1; c = getchar();}while(isdigit(c)){x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}return x * f;
}
struct matrix{LL mat[3][3];friend matrix operator * (matrix a, matrix b){matrix c;memset(c.mat, 0, sizeof c.mat);    	for(int i = 0; i < 3; i++)for(int j = 0; j < 3; j++)for(int k = 0; k < 3; k++)c.mat[i][j] = (c.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % mod;return c;}
};
struct SegmentTree{int l, r; matrix c;#define l(x) t[x].l#define r(x) t[x].r#define c(x) t[x].c
}t[N * 4];
int n, m, T, sx, sy, ex, ey;
LL a[2][N];
void update(int p){c(p) = c(p << 1) * c(p << 1 | 1);}
void build(int p, int l, int r){l(p) = l, r(p) = r;if(l == r){c(p).mat[0][0] = a[0][l] % mod; c(p).mat[1][0] = (a[0][l] * a[1][l]) % mod; c(p).mat[2][0] = 0;c(p).mat[0][1] = (a[0][l] * a[1][l]) % mod; c(p).mat[1][1] = a[1][l] % mod; c(p).mat[2][1] = 0;c(p).mat[0][2] = 1; c(p).mat[1][2] = 1; c(p).mat[2][2] = 1;return ;}int mid = (l + r >> 1);build(p << 1, l, mid);build(p << 1 | 1, mid + 1, r);update(p);
}
matrix ask(int p, int l, int r){if(l <= l(p) && r >= r(p)) return c(p);int mid = (l(p) + r(p) >> 1);if(r <= mid) return ask(p << 1, l, r);else if(l > mid) return ask(p << 1 | 1, l, r);else return ask(p << 1, l, r) * ask(p << 1 | 1, l, r);
}
LL query(int sx, int sy, int ex, int ey){matrix res;res.mat[0][sx] = a[sx][sy];res.mat[0][1 - sx] = (a[sx][sy] * a[1 - sx][sy]) % mod;if(sy != ey){matrix tmp = ask(1, sy + 1, ey);res = res * tmp;}return res.mat[0][ex];
}
LL solve(){LL res = 0;for(int i = 1; i <= n; i++){//枚举起点 for(int j = 0; j <= 1; j++){matrix tmp;tmp.mat[0][j] = a[j][i];tmp.mat[0][1 - j] = (a[j][i] * a[1 - j][i]) % mod;tmp.mat[0][2] = 0;if(i != n){matrix cur = ask(1, i + 1, n);tmp = tmp * cur;} res = (res + tmp.mat[0][2] + tmp.mat[0][0] + tmp.mat[0][1]) % mod;}}return res;
}
int main(){m = read(), n = read(), T = read();for(int i = 0; i < m; i++)for(int j = 1; j <= n; j++)a[i][j] = 1LL * read() % mod;build(1, 1, n);//构建矩阵if(T){while(T--){	sx = read(), sy = read(), ex = read(), ey = read();sx--, ex--;printf("%lld\n", query(sx, sy, ex, ey));}} else printf("%lld\n", solve());return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/132740.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python基础(Python高级特性(切片、列表生成式)、字符串的正则表达式、函数、模块、Python常用内置函数、错误处理)培训讲义

文章目录 1. Python高级特性&#xff08;切片、列表生成式&#xff09;a) 切片的概念、列表/元组/字符串的切片切片的概念列表切片基本索引简单切片超出有效索引范围缺省 扩展切片step为正数step为负数 b) 列表生成式以及使用列表生成式需要注意的地方概念举例说明1. 生成一个列…

【移远QuecPython】EC800M物联网开发板的内置GNSS定位的恶性BUG(目前没有完全的解决方案)

【移远QuecPython】EC800M物联网开发板的内置GNSS定位的恶性BUG&#xff08;目前没有完全的解决方案&#xff09; GNSS配置如下&#xff1a; 【移远QuecPython】EC800M物联网开发板的内置GNSS定位获取&#xff08;北斗、GPS和GNSS&#xff09; 测试视频&#xff08;包括BUG复…

简单CMake入门

CMake可以生成不同平台下的Makefile&#xff0c;有了CMake不用再写复杂的Makefile 视频教程&#xff1a;CMake 6分钟入门&#xff0c;不用再写复杂的Makefile 先前知识 Makefile简单入门 Cmake特性 CMake是一个用于管理C/C项目的跨平台构建工具。 跨平台&#xff1a;CMake是…

【漏洞复现】Apache Log4j Server 反序列化命令执行漏洞(CVE-2017-5645)

感谢互联网提供分享知识与智慧&#xff0c;在法治的社会里&#xff0c;请遵守有关法律法规 文章目录 1.1、漏洞描述1.2、漏洞等级1.3、影响版本1.4、漏洞复现1、基础环境2、漏洞扫描3、漏洞验证 1.5、深度利用1、反弹Shell 说明内容漏洞编号CVE-2017-5645漏洞名称Log4j Server …

判断字符串是否为json

//营业时间返回数组String businessDate merchantInfoResp.getBusinessDate();Object obj JSON.parse(businessDate);if (obj instanceof JSONArray) {merchantInfoResp.setBusinessDateDesc(JSON.parseArray(JSON.toJSONString(obj), Integer.class));} else {//营业日期判断…

Ubuntu下安装vscode,并解决终端打不开vscode的问题

Visual Studio Code安装 1&#xff0c;使用 apt 安装 Visual Studio Code 在官方的微软 Apt 源仓库中可用。按照下面的步骤进行即可&#xff1a; 以 sudo 用户身份运行下面的命令&#xff0c;更新软件包索引&#xff0c;并且安装依赖软件&#xff1a; sudo apt update sud…

09 基变换

基变换 基本概念坐标转换詹妮弗坐标系→平面直角坐标系平面直角坐标系→詹妮弗坐标系转换对比基本原则 这是关于3Blue1Brown "线性代数的本质"的学习笔记。 基本概念 对于右手平面直角坐标系&#xff0c;一般用 i ⃗ \vec{i} i 和 j ⃗ \vec{j} j ​表示其基向量。…

86.Linux系统下复制进程fork(逻辑地址和物理地址)

目录 fork复制进程 逻辑地址和物理地址 fork复制进程 fork 是一个系统调用&#xff0c;在 Linux/Unix 系统中用于创建一个新的进程&#xff0c;新进程称为子进程。子进程是父进程的副本&#xff0c;它从父进程那里继承了大部分属性和资源&#xff0c;包括代码、数据、打开的文…

VMware 虚拟机安装 CentOS 7

CentOS 7 1. 下载CentOS 7 iso镜像 Index of /centos/7.9.2009/isos/x86_64/ 2. Vmware安装CentOS 7 安装教程&#xff1a; 超详细VMware CentOS7(最小安装)安装教程_虚拟机最小化安装-CSDN博客 【精选】VMware 安装 Centos7 详细过程_vm虚拟机安装centos7_expectation Fu…

网络原理---封装和分用

文章目录 什么是封装和分用&#xff1f;封装应用层传输层网络层数据链路层物理层 分用物理层数据链路层网络层传输层应用层 什么是封装和分用&#xff1f; 我们前面讲过协议会分层&#xff0c;每一层都有各自的功能。而在数据传输的过程中&#xff0c;得按照顺序把每一层协议都…

【ArcGIS微课1000例】0077:ArcGIS生成经纬网(shp格式)

使用ArcGIS制图的时候,可以很方便的生成经纬网、方里网及参考格网,但是在需要shp格式的经纬网,进一步在南方cass中使用经纬网的时候,就需要单独生成了。 如下图所示为全球大陆矢量数据,我们基于该数据来生成全球指定间距的经纬网数据。 在ArcGIS中,生成经纬网和方里网均…

音乐推荐与管理系统Python+Django网页界面+协同过滤推荐算法

一、介绍 音乐推荐与管理系统。本系统采用Python作为主要开发语言&#xff0c;前端使用HTML、CSS、BootStrap等技术搭建界面平台&#xff0c;后端使用Django框架处理请求&#xff0c;并基于Ajax等技术实现前端与后端的数据通信。在音乐个性推荐功能模块中采用通过Python编写协…

ARMday1

1、计算机的组成 输入设备-输出设备-运算器-控制器-存储器 输入设备&#xff1a;键盘、鼠标、手柄、扫描仪 输出设备&#xff1a;显示屏、打印机、音响 存储器&#xff1a;存放数据以及指令、是实现“程序存储控制”的基础、外存、内存、cache、寄存器 控制器&#xff08;…

django安装数据库

使用pip安装django pip3 install django注意我使用的是python3所以用pip3安装&#xff0c;如需安装指定版本 django ..* 检测是否安装成功,不报错&#xff0c;则安装成功 # python3 # import django下边这是报错的 django迁移数据库 再mysql中简历数据库 CREATE DATABA…

chinese-stable-diffusion中文场景文生图prompt测评集合

腾讯混元大模型文生图操作指南.dochttps://mp.weixin.qq.com/s/u0AGtpwm_LmgnDY7OQhKGg腾讯混元大模型再进化&#xff0c;文生图能力重磅上线&#xff0c;这里是一手实测腾讯混元的文生图在人像真实感、场景真实感上有比较明显的优势&#xff0c;同时&#xff0c;在中国风景、动…

【PyQt学习篇 · ⑪】:QPushButton和QCommandLinkButton的使用

文章目录 构造函数菜单设置扁平化默认处理右键菜单QCommandLinkButton的使用 构造函数 QPushButton的构造函数如下&#xff1a; """QPushButton(parent: Optional[QWidget] None)QPushButton(text: Optional[str], parent: Optional[QWidget] None)QPushButt…

【QT】 Qt自定义ui控件

在使用Qt的ui设计时&#xff0c;Qt为我们提供了标准的窗口控件&#xff0c;但是在很多复杂工程中&#xff0c;标准窗口控件并不能满足所有的需求&#xff0c;这时就需要我们自定义控件。我们自定义的类既可以作为独立的窗口显示&#xff0c;又可以作为一个控件显示。 我们要实现…

Flink SQL DataGen Connector 示例

Flink SQL DataGen Connector 示例 1、概述 使用 Flink SQL DataGen Connector&#xff0c;可以快速地生成符合规则的测试数据&#xff0c;可以在不依赖真实数据的情况下进行开发和测试。 2、使用示例 创建一个名为 “users” 的表&#xff0c;包含 6 个字段&#xff1a;id…

【Leetcode】349. 两个数组的交集

题意 给定两个数组&#xff0c;编写一个函数来计算它们的交集。 说明&#xff1a; 输出结果中的每个元素一定是唯一的。 我们可以不考虑输出结果的顺序。 思路 这道题目&#xff0c;主要要学会使用一种哈希数据结构&#xff1a;unordered_set&#xff0c;这个数据结构可以解决…

【Redis】hash数据类型-常用命令

文章目录 前置知识常用命令HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGET关于HMSETHLENHSETNXHINCRBYHINCRBYFLOAT 命令小结 前置知识 redis自身就是键值对结构了&#xff0c;哈希类型是指值本⾝⼜是⼀个键值对结构&#xff0c;形如key"key"&#xff0c;value{{field1…