洛谷 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- ...
随机推荐
- 【Spring】重新认识 IoC
前言 IoC (Inversion of control) 并不是Spring特有的概念. IoC 维基百科的解释: In software engineering, inversion of con ...
- 【UE4 设计模式】组件模式 Components Pattern
概述 描述 在单一实体跨越了多个领域时,为了保持领域之间相互解耦,可以将每部分代码放入各自的组件类中,将实体简化为组件的容器. 套路 参考 UE4中的 Componet 组件使用方式 使用场景 有一个 ...
- pagelayout在py中的引用不支持size_hint和pos_hint
from kivy.uix.pagelayout import PageLayout from kivy.uix.button import Button from kivy.app import A ...
- [对对子队]会议记录5.17(Scrum Meeting4)
今天已完成的工作 何瑞 工作内容:实现选择组件,搭建第7关 相关issue:实现选择组件 相关签入:feature:完成Lv7的UI搭建 吴昭邦 工作内容:实现选择组件,搭建第7关 ...
- mongodb的简单查询
此篇文章简单的记录一下mongodb 的简单查询操作. 一.数据准备: db.persons.insertMany([ {'userId':1,name:'张三','age':20,'scores': ...
- Huffman算法
一.Huffman算法介绍 霍夫曼编码(英语:Huffman Coding),又译为哈夫曼编码.赫夫曼编码,是一种用于无损数据压缩的熵编码(权编码)算法.在计算机数据处理中,霍夫曼编码使用变长编码表对 ...
- Linkerd 2:5 分种厘清 Service Mesh 相关术语
API Gateway(API 网关) API gateway 位于应用程序的前面,旨在解决身份验证和授权.速率限制以及为外部消费者提供公共访问点等业务问题. 相比之下,service mesh 专注 ...
- 图像原始格式(YUV444 YUV422 YUV420)一探究竟
前段时间搞x264编码测试,传参的时候需要告诉编码器我的原始数据格式是什么,其中在x264.h头文件中定义了如下一堆类型. /* Colorspace type */ #define X264_CSP ...
- Linux上Qt旋转显示
对于嵌入式设备来说用于显示的LCD总是千奇百怪,比如说明明是一个竖屏,但是客户却要当横屏使用,也就是意味着我们需要将整个屏幕上显示的内容旋转90度或者270度. 这个操作对于Android系统来说相当 ...
- netfilter/iptables 学习
netfilter概述 netfilter 组件位于内核空间(kernelspace),是内核的一部分,由一些信息包过滤表组成,这些表包含内核用来控制信息包过滤处理的规则集. iptables 组件是 ...