题面传送门

题意:

有一张 \(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]美食家(广义矩阵快速幂)的更多相关文章

  1. 洛谷P3758/BZOJ4887 [TJOI2017] 可乐 [矩阵快速幂]

    洛谷传送门,BZOJ传送门 可乐 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 299  Solved: 207 Description 加里敦星球的人 ...

  2. 洛谷P3390【模板】矩阵快速幂——矩阵运算入门笔记

    作为一个因为极度畏惧数学 而选择成为一名OIer的蒟蒻 终于还是迎来了要面对的这一天 一般题目中矩阵运算好像只用到矩阵乘法 (或许只是蒟蒻我做的题太少) 而且矩阵的乘法也是较难理解的一部分 所以就简单 ...

  3. 洛谷P3390 【模板】矩阵快速幂

    给定n*n的矩阵A,求A^k 行列都是n #include <iostream> #include <cstdio> #include <cstring> #inc ...

  4. 洛谷 P3390 【模板】矩阵快速幂

    这题的确是个模板 但也要提到有关矩乘的内容: 首先什么是矩阵? 给一个线性变换 F(x)   (她可能就是个函数,定义域为向量集) 她可以把一个N维向量变成M维 那么显然x的每一维都可能影响着F(x) ...

  5. 题解——洛谷P3390 【模板】矩阵快速幂(矩阵乘法)

    模板题 留个档 #include <cstdio> #include <algorithm> #include <cstring> #define int long ...

  6. 【洛谷】P1313 计算系数(快速幂+杨辉三角)

    题目 题目描述 给定一个多项式(by+ax)^k,请求出多项式展开后x^n*y^m 项的系数. 输入输出格式 输入格式: 输入文件名为factor.in. 共一行,包含5 个整数,分别为 a ,b , ...

  7. 洛谷 P1045 麦森数 (快速幂+高精度+算位数骚操作)

    这道题太精彩了! 我一开始想直接一波暴力算,然后叫上去只有50分,50分超时 然后我改成万位制提高运算效率,还是只有50分 然后我丧心病狂开long long用10的10次方作为一位,也就是100亿进 ...

  8. NOIP2003 普及组 洛谷P1045 麦森数 (快速幂+高精度)

    有两个问题:求位数和求后500位的数. 求位数:最后减去1对答案的位数是不影响的,就是求2p的位数,直接有公式log10(2)*p+1; 求后500位的数:容易想到快速幂和高精度: 1 #includ ...

  9. 洛谷P5245 【模板】多项式快速幂(多项式ln 多项式exp)

    题意 题目链接 Sol \(B(x) = \exp(K\ln(A(x)))\) 做完了... 复杂度\(O(n\log n)\) // luogu-judger-enable-o2 // luogu- ...

随机推荐

  1. 【UE4 C++】碰撞检测与事件绑定

    概念 碰撞对象通道与预设 默认提供碰撞对象类型,如 WorldStatic.WorldDynamic等.允许用户自定义 默认提供碰撞预设,如 NoCollision.BloackAll.Overlap ...

  2. [技术博客] K-Means算法

    遇到的问题 在对微软\(OCR\)的\(api\)进行测试的过程中,我发现有时候它并不能分析出一个表格的形态,也就是说不知道每个文本对应在表格中的第几行第几列.但是它可以较为准确的给出这些文本的坐标. ...

  3. BUAA_2020_软件工程_热身作业

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任建) 这个作业的要求在哪里 热身作业要求 我在这个课程的目标 了解软件工程的技术,掌握工程化开发的能力 这个作业在哪个具体方面 ...

  4. 绘制PCB电路原理图的8种方法

    1.选择集成电路,变压器,晶体管等组件,这些组件体积庞大,有许多引脚并在电路中起主要作用,然后从选定的参考引脚中抽取,以减少错误. 2.如果PCB上标有元件编号(如VD870,R330,C466等), ...

  5. 计算机网络之网络层IP组播(IGMP、组播路由选择协议、组播地址)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105318560 学习课程:<2019王道考研计算机网络> 学习目的 ...

  6. shell 匿名管道和命名管道

    管道的特点:如果管道中没有数据,那么取管道数据的操作就会滞留,直到管道内进入数据,然后读出后才会终止这一操作:同理,写入管道的操作如果没有读取管道的操作,这一动作也会滞留. 1,匿名管道 匿名管道使用 ...

  7. Python 检查当前运行的python版本 python2 python3

    检查当前运行的python版本,可以帮助程序选择运行python2还是python3的代码 import sys if sys.version > '3': PY3 = True else: P ...

  8. cf20B Equation(认真仔细题)

    题意: 求AX^2+BX+C=0的根 思路: 考虑到A,B,C所有可能的情况 代码: double a,b,c; int main(){ cin>>a>>b>>c; ...

  9. hdu 5178 pairs(BC第一题,,方法不止一种,,我用lower_bound那种。。。)

    题意: X坐标上有n个数.JOHN想知道有多少对数满足:x[a]-x[b]<=k(题意给)[a<b] 思路: 额,,,直接看代码吧,,,, 代码: int T,n,k; int x[100 ...

  10. Spring Cloud 微服务实战——nacos 服务注册中心搭建(附源码)

    作为微服务的基础功能之一的注册中心担任重要的角色.微服务将单体的服务拆分成不同的模块下的服务,而不同的模块的服务如果进行通信调用呢?这就需要服务注册与发现.本文将使用阿里开源项目 nacos 搭建服务 ...