题面传送门

题意:

有一张 \(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. 初学python-day4 字典(已更新完)

  2. vue2和vue3比较

    一.vue3新特性: 1.数据响应重新实现(ES6的proxy代替Es5的Object.defineProperty) 2.源码使用ts重写,更好的类型推导 3.虚拟DOM新算法(更快,更小) 4.提 ...

  3. RabbitMQ延时队列应用场景

    应用场景 我们系统未付款的订单,超过一定时间后,需要系统自动取消订单并释放占有物品 常用的方案 就是利用Spring schedule定时任务,轮询检查数据库 但是会消耗系统内存,增加了数据库的压力. ...

  4. Alpha Scrum Meeting汇总

    第一次Alpha Scrum Meeting 第二次Alpha Scrum Meeting 第三次Alpha Scrum Meeting 第四次Alpha Scrum Meeting 第五次Alpha ...

  5. Beta-功能规格说明书

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-计划-功能规格说明书 一.引言 1. 项目简介 项目团队:删库跑路对不队 项目名称:题士 项目内容 ...

  6. Sharding-JDBC自定义复合分片算法

    Sharding-JDBC自定义复合分片算法 一.背景 二.需求 1.对于客户端操作而言 2.对于运营端操作而言 三.分片算法 1.客户id和订单id的生成规则 2. 确定数据落在那个表中 3.举例说 ...

  7. Linux多线程编程实例解析

    Linux系统下的多线程遵循POSIX线程接口,称为 pthread.编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a.顺便说一下,Linux ...

  8. sonar-project.propertie分析参数

    SonarScanner 是当您的构建系统没有特定扫描仪时使用的扫描仪. 配置您的项目 在你的项目根目录中创建一个名为的配置文件 sonar-project.properties # must be ...

  9. Go语言核心36讲(Go语言进阶技术十)--学习笔记

    16 | go语句及其执行规则(上) 我们已经知道,通道(也就是 channel)类型的值,可以被用来以通讯的方式共享数据.更具体地说,它一般被用来在不同的 goroutine 之间传递数据.那么 g ...

  10. Allure快速入门

    1.关于Allure     Allure框架是一个灵活轻量级多语言测试报告工具,它不仅可以以WEB的方式展示简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息.   ...