洛谷 P6772 - [NOI2020]美食家(广义矩阵快速幂)
题意:
有一张 \(n\) 个点 \(m\) 条边的有向图,第 \(0\) 天的时候你在 \(1\) 号城市,第 \(T\) 天的时候你要回到 \(1\) 号城市。
每条边上的边权表示从城市 \(u_i\) 到达 \(v_i\) 需要的天数。
你每次到达城市 \(i\) 就会获得 \(c_i\) 的愉悦值
另外有 \(k\) 个三元组 \((t_i,x_i,y_i)\) 表示如果你第 \(t_i\) 天到达城市 \(x_i\) 就可以额外获得 \(y_i\) 的愉悦值
求最大愉悦值。
\(n \leq 50\),\(T \leq 10^9\),\(k \leq 200\),\(w_i \leq 5\)
大家好,这就是那个考场上想到广义矩阵快速幂却没写的人。
感觉这题就是 P6190+CF576D+P3715
当时三题一题都没做过,现在三题都做过了回来看这题就很简单了。
朴素 \(dp\) 特别容易,\(dp_{i,j}\) 表示经过 \(i\) 天到达 \(j\) 号城市获得的最大愉悦值。
考虑优化,先假设 \(k=0\),所有 \(w_i\) 都等于 \(1\)。
那么就有 \(dp_{t,v_i}=\max\{dp_{t-1,u_i}+c_{v_i}\}\)
用广义矩阵乘法 \(c_{i,j}=\max\{a_{i,k}+b_{k,j}\}\) 的方式转移即可。
再考虑 \(w_i\neq 1\) 的情况。我们可以将转移矩阵扩充到 \((5n)\times(5n)\),用一个 \(1\times 5n\) 的矩阵记录 \(dp_{i},dp_{i-1},dp_{i-2},dp_{i-3},dp_{i-4}\) 的值进行转移。
最后考虑 \(k\neq 0\),把所有美食节按 \(t_i\) 从小到大排序,然后分段转移。
这样是 \(k(5n)^3\log T\) 的,显然不行。
不过一个 \(n\times m\) 的矩阵与 \(m\times k\) 的矩阵相乘,所谓的 \(n^3\),实际上是 \(nmk\),也就是说,我们可以预处理出转移矩阵的 \(2^k\) 的幂,然后每次转移的时候用那个 \(1\times (5n)\) 的矩阵与其做一遍矩阵乘法,这样复杂度就降到了 \((5n)^2k\log T\)。
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define fz(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define ffe(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define fill0(a) memset(a,0,sizeof(a))
#define fill1(a) memset(a,-1,sizeof(a))
#define fillbig(a) memset(a,63,sizeof(a))
#define pb push_back
#define ppb pop_back
#define mp make_pair
template<typename T1,typename T2> void chkmin(T1 &x,T2 y){if(x>y) x=y;}
template<typename T1,typename T2> void chkmax(T1 &x,T2 y){if(x<y) x=y;}
typedef pair<int,int> pii;
typedef long long ll;
template<typename T> void read(T &x){
char c=getchar();T neg=1;
while(!isdigit(c)){if(c=='-') neg=-1;c=getchar();}
while(isdigit(c)) x=x*10+c-'0',c=getchar();
x*=neg;
}
const int MAXN=50;
const int MAXK=200;
const int LOG_T=30;
int n,m,T,k,c[MAXN+5];
struct mat{
int N,M;ll a[MAXN*5+5][MAXN*5+5];
mat(){for(int i=1;i<=MAXN*5;i++) for(int j=1;j<=MAXN*5;j++) a[i][j]=-1e18;}
friend mat operator *(mat x,mat y){
mat ret;ret.N=x.N;ret.M=y.M;
for(int i=1;i<=x.N;i++) for(int j=1;j<=x.M;j++)
for(int k=1;k<=y.M;k++) chkmax(ret.a[i][j],x.a[i][k]+y.a[k][j]);
return ret;
}
} tr[LOG_T+2],cur;
struct event{
int t,x,y;
friend bool operator <(event a,event b){
return a.t<b.t;
}
} a[MAXK+5];
int main(){
// freopen("deligacy.in","r",stdin);freopen("deligacy.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&T,&k);
for(int i=1;i<=n;i++) scanf("%d",&c[i]);
for(int i=1;i<=n;i++) for(int j=0;j<4;j++) tr[0].a[j*n+n+i][j*n+i]=0;
tr[0].N=tr[0].M=5*n;
for(int i=1;i<=m;i++){
int u,v,w;scanf("%d%d%d",&u,&v,&w);
chkmax(tr[0].a[(5-w)*n+u][4*n+v],c[v]);
}
cur.N=1;cur.M=5*n;cur.a[1][4*n+1]=c[1];
for(int i=1;i<=LOG_T;i++) tr[i]=tr[i-1]*tr[i-1];
int pre=0;
for(int i=1;i<=k;i++) scanf("%d%d%d",&a[i].t,&a[i].x,&a[i].y);
sort(a+1,a+k+1);
for(int i=1;i<=k;i++){
int dis=a[i].t-pre;pre=a[i].t;
for(int j=0;j<=LOG_T;j++) if(dis>>j&1) cur=cur*tr[j];
cur.a[1][n*4+a[i].x]+=a[i].y;
}
int dis=T-pre;
for(int j=0;j<=LOG_T;j++) if(dis>>j&1) cur=cur*tr[j];
if(cur.a[1][4*n+1]<0) puts("-1");
else printf("%lld\n",cur.a[1][4*n+1]);
return 0;
}
洛谷 P6772 - [NOI2020]美食家(广义矩阵快速幂)的更多相关文章
- 洛谷P3758/BZOJ4887 [TJOI2017] 可乐 [矩阵快速幂]
洛谷传送门,BZOJ传送门 可乐 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 299 Solved: 207 Description 加里敦星球的人 ...
- 洛谷P3390【模板】矩阵快速幂——矩阵运算入门笔记
作为一个因为极度畏惧数学 而选择成为一名OIer的蒟蒻 终于还是迎来了要面对的这一天 一般题目中矩阵运算好像只用到矩阵乘法 (或许只是蒟蒻我做的题太少) 而且矩阵的乘法也是较难理解的一部分 所以就简单 ...
- 洛谷P3390 【模板】矩阵快速幂
给定n*n的矩阵A,求A^k 行列都是n #include <iostream> #include <cstdio> #include <cstring> #inc ...
- 洛谷 P3390 【模板】矩阵快速幂
这题的确是个模板 但也要提到有关矩乘的内容: 首先什么是矩阵? 给一个线性变换 F(x) (她可能就是个函数,定义域为向量集) 她可以把一个N维向量变成M维 那么显然x的每一维都可能影响着F(x) ...
- 题解——洛谷P3390 【模板】矩阵快速幂(矩阵乘法)
模板题 留个档 #include <cstdio> #include <algorithm> #include <cstring> #define int long ...
- 【洛谷】P1313 计算系数(快速幂+杨辉三角)
题目 题目描述 给定一个多项式(by+ax)^k,请求出多项式展开后x^n*y^m 项的系数. 输入输出格式 输入格式: 输入文件名为factor.in. 共一行,包含5 个整数,分别为 a ,b , ...
- 洛谷 P1045 麦森数 (快速幂+高精度+算位数骚操作)
这道题太精彩了! 我一开始想直接一波暴力算,然后叫上去只有50分,50分超时 然后我改成万位制提高运算效率,还是只有50分 然后我丧心病狂开long long用10的10次方作为一位,也就是100亿进 ...
- NOIP2003 普及组 洛谷P1045 麦森数 (快速幂+高精度)
有两个问题:求位数和求后500位的数. 求位数:最后减去1对答案的位数是不影响的,就是求2p的位数,直接有公式log10(2)*p+1; 求后500位的数:容易想到快速幂和高精度: 1 #includ ...
- 洛谷P5245 【模板】多项式快速幂(多项式ln 多项式exp)
题意 题目链接 Sol \(B(x) = \exp(K\ln(A(x)))\) 做完了... 复杂度\(O(n\log n)\) // luogu-judger-enable-o2 // luogu- ...
随机推荐
- python filter lambda 的使用
lambda 匿名函数的使用 >>> a=lambda x : x in "1234567890.," >>> a("asd" ...
- Java 读取PDF中的表格
一.概述 本文以Java示例展示读取PDF中的表格的方法.这里导入Spire.PDF for Javah中的jar包,并使用其提供的相关及方法来实现获取表格中的文本内容.下表中整理了本次代码使用到的主 ...
- [no code][scrum meeting] Beta 4
例会时间:5月16日11:30,主持者:伦泽标 下次例会时间:5月18日11:30,主持者:叶开辉 一.工作汇报 人员 昨日完成任务 明日要完成的任务 乔玺华 完成整体框架设计与登录逻辑 与后端对接 ...
- 大牛针对零基础入门c语言详解指针(超详细)
C语言指针说难不难但是说容易又是最容易出错的地方,因此不管是你要做什么只要用到C指针你就跳不过,今天咱们就以 十九个例子来给大家简单的分析一下指针的应用,最后会有C语言视频资料提供给大家更加深入的参考 ...
- 【做题记录】[NOIP2016 普及组] 魔法阵
P2119 魔法阵 2016年普及组T4 题意: 给定一系列元素 \(\{X_i\}\) ,求满足以下不等式的每一个元素作为 \(a,b,c,d\) 的出现次数 . \[\begin{cases}X_ ...
- MVC下垃框的使用
--------------模型-------------------- /// <summary> /// 状态 /// =0 下架 =1 上架 /// </summary> ...
- 【lwip】04-内存管理
目录 前言 4. 内存管理 4.1 内存分配策略 4.1.1 固定大小的内存块 4.1.2 可变大小分配 4.2 动态内存池(pool) 4.2.1 介绍 4.2.2 内存池的预处理 4.2.3 内存 ...
- FastJson 解析、序列化及反序列化
一.环境准备:使用maven特性在pom.xml中导入fastjson的依赖包 <!-- https://mvnrepository.com/artifact/com.alibaba/fastj ...
- 使用silky脚手架构建微服务应用
目录 模板简介 构建独立应用的模板Silky.App.Template 构建模块化应用的模板Silky.Module.Template 开源地址 在线文档 模板简介 使用 dotnet new 命令可 ...
- robot_framewok自动化测试--(7)认识RIDE
认识 RIDE RIDE 作为 Robot Framework 的"脸面",虽然我们已经可以拿它来创建和运行测试了,但我们对它的认识并不全面,这一小节我们将了解这个工具的使用. 1 ...