传送门:QAQQAQ

完了完了NOI签到题全班打不出来,真就全部成为时代的眼泪了。。。

首先$O(mT)$的$dp$显然,然后因为$T$很大$w$很小矩阵快速幂显然,但是有$k=200$卡不过去。

然后因为行向量乘上转移矩阵是$O(n^{2})$的,所以我们枚举的$k$时只用行向量乘上转移矩阵,转移矩阵的自乘放在外面倍增预处理,这样复杂度是$O(n^{2}*k*log(V)+(n^{3}*log(V)))$,开了O2非常稳

所以最近两道几乎正解的矩乘都没打出来。。一道倍增预处理转移矩阵优化,一道先DFT转点值再快速幂而不是每次快速幂用FFT优化来降复杂度。。

菜是原罪。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const ll inf=(ll)1e15;
#define mk make_pair
void checkmin(ll &x,ll y){if(x>y) x=y;}
void checkmax(ll &x,ll y){if(x<y) x=y;}
const int N=2010;
vector<pii> v[N],G[N];
int t[N],X[N],Y[N],c[N];
int n,m,T,k;
struct Edge
{
int from,to,cost;
}E[N]; void init()
{
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<=m;i++)
{
scanf("%d%d%d",&E[i].from,&E[i].to,&E[i].cost);
v[E[i].from].push_back(mk(E[i].to,E[i].cost));
G[E[i].to].push_back(mk(E[i].from,E[i].cost));
}
for(int i=1;i<=k;i++) scanf("%d%d%d",&t[i],&X[i],&Y[i]);
} namespace solver1{
ll dp[52600][55]; int a[52600][55];
void init()
{
memset(a,0,sizeof(a));
for(int i=1;i<=k;i++) a[t[i]][X[i]]=Y[i];
}
void main()
{
init();
for(int i=0;i<=T;i++)
for(int j=1;j<=n;j++) dp[i][j]=-inf;
dp[0][1]=c[1];
for(int i=1;i<=T;i++)
{
for(int j=1;j<=n;j++)
{
for(int p=0;p<(int)G[j].size();p++)
{
int to=G[j][p].first,w=G[j][p].second;
if(i<w) continue;
checkmax(dp[i][j],dp[i-w][to]+c[j]);
}
}
for(int j=1;j<=n;j++) dp[i][j]+=a[i][j];
}
if(dp[T][1]<=0) puts("-1");
else printf("%lld\n",dp[T][1]);
}
} struct matrix{
ll a[255][255];
int n,m;
matrix(){}
matrix(int n,int m):n(n),m(m){
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) a[i][j]=-inf;
}
}; matrix operator * (matrix A,matrix B)
{
matrix C(A.n,B.m);
for(int i=1;i<=C.n;i++)
{
for(int k=1;k<=A.m;k++)
{
if(A.a[i][k]==-inf) continue;
for(int j=1;j<=C.m;j++)
checkmax(C.a[i][j],A.a[i][k]+B.a[k][j]);
}
}
return C;
} struct LI{
int t,x,y;
LI(){}
LI(int t,int x,int y):t(t),x(x),y(y){}
bool operator < (const LI &rhs) const{
return t<rhs.t;
}
}limit[N]; matrix Base[31];
void Qpow(matrix &A,int y)
{
matrix ret(A.n,A.m);
for(int i=1;i<=A.n;i++) ret.a[i][i]=0;
for(int i=30;i>=0;i--)
{
if((1<<i)<=y) y-=(1<<i),A=A*Base[i];
}
} namespace solver2{
ll dp1[7][55]; int a[7][55];
void init()
{
memset(a,0,sizeof(a));
for(int i=1;i<=k;i++)
if(t[i]<=5) a[t[i]][X[i]]=Y[i];
}
void build()
{
init();
for(int i=0;i<=5;i++)
for(int j=1;j<=n;j++) dp1[i][j]=-inf;
dp1[0][1]=c[1];
for(int i=1;i<=5;i++)
{
for(int j=1;j<=m;j++)
{
int u=E[j].from,to=E[j].to,w=E[j].cost;
if(i<E[j].cost) continue;
if(dp1[i-w][u]==-inf) continue;
checkmax(dp1[i][to],dp1[i-w][u]+c[to]);
}
for(int j=1;j<=n;j++) dp1[i][j]+=a[i][j];
}
}
void main()
{
build();
int TMP=0;
for(int i=1;i<=k;i++)
{
if(t[i]<=5) i--,k--,TMP++;
limit[i]=LI(t[i+TMP],X[i+TMP],Y[i+TMP]);
}
sort(limit+1,limit+k+1);
matrix A(1,n*5);
for(int i=1;i<=5;i++)
{
for(int j=1;j<=n;j++) A.a[1][(i-1)*n+j]=dp1[i][j];
}
//print(A);
for(int i=0;i<=30;i++)
{
Base[i].m=Base[i].n=5*n;
for(int j=1;j<=5*n;j++)
{
for(int t=1;t<=5*n;t++)
{
Base[i].a[j][t]=-inf;
}
}
}
for(int j=1;j<=n*4;j++) Base[0].a[j+n][j]=0;
for(int i=1;i<=m;i++)
{
int u=E[i].from,to=E[i].to,w=E[i].cost;
int from=(5-w)*n+u; to=4*n+to;
Base[0].a[from][to]=c[E[i].to];
}
//print(Base);
for(int i=1;i<=30;i++) Base[i]=Base[i-1]*Base[i-1]; T-=5;
for(int i=1;i<=k;i++) limit[i].t-=5;
int now=0;
for(int i=1;i<=k;i++)
{
int pos=limit[i].t;
Qpow(A,pos-now);
now=pos;
if(A.a[1][4*n+limit[i].x]==-inf) continue;
else A.a[1][4*n+limit[i].x]+=limit[i].y;
} Qpow(A,T-now);
if(A.a[1][4*n+1]<=0) puts("-1");
else printf("%lld\n",A.a[1][4*n+1]);
}
} namespace solver3{
int dis[N],vis[N];
ll tot=0;
void dfs(int u){
if(vis[u]) return;
vis[u]=1;
for(int i=0;i<(int)v[u].size();i++)
{
int to=v[u][i].first,w=v[u][i].second;
dis[to]=dis[u]+w;
dfs(to);
}
}
void main()
{
memset(vis,0,sizeof(vis)); dis[1]=0;
dfs(1);
if(T%dis[1]!=0)
{
puts("-1");
return;
}
ll ans=c[1];
for(int i=1;i<=k;i++)
{
if((t[i]-dis[X[i]])%dis[1]==0) ans+=Y[i];
}
for(int i=1;i<=n;i++) tot+=c[i];
ans+=T/dis[1]*tot;
printf("%lld\n",ans);
}
} bool iscircle()
{
if(n!=m) return 0;
for(int i=1;i<=m;i++)
{
if(E[i].to!=E[i].from%n+1) return 0;
}
return 1;
} void solve()
{
if(T<=52600)
{
solver1::main();
return;
}
if(iscircle())
{
solver3::main();
return;
}
solver2::main();
return;
} int main()
{
//freopen("delicacy.in","r",stdin);
//freopen("delicacy.out","w",stdout);
init();
solve();
fclose(stdin); fclose(stdout);
return 0;
}

NOI2020D1T1美食家的更多相关文章

  1. BZOJ 1691: [Usaco2007 Dec]挑剔的美食家 [treap 贪心]

    1691: [Usaco2007 Dec]挑剔的美食家 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 786  Solved: 391[Submit][S ...

  2. [BZOJ1691][Usaco2007 Dec]挑剔的美食家

    [BZOJ1691][Usaco2007 Dec]挑剔的美食家 试题描述 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返了. ...

  3. BZOJ 1691: [Usaco2007 Dec]挑剔的美食家( 平衡树 )

    按鲜嫩程度排个序, 从大到小处理, 用平衡树维护价值 ---------------------------------------------------------------------- #i ...

  4. BZOJ_1691_[Usaco2007 Dec]挑剔的美食家_贪心

    BZOJ_1691_[Usaco2007 Dec]挑剔的美食家_贪心 题意: 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一去不返 ...

  5. 51nod 挑剔的美食家

    挑剔的美食家    基准时间限制:1 秒 空间限制:131072 KB 分值: 5 与很多奶牛一样,Farmer John那群养尊处优的奶牛们对食物越来越挑剔,随便拿堆草就能打发她们午饭的日子自然是一 ...

  6. Java实现 蓝桥杯VIP 算法提高 聪明的美食家

    算法提高 聪明的美食家 时间限制:1.0s 内存限制:256.0MB 问题描述 如果有人认为吃东西只需要嘴巴,那就错了. 都知道舌头有这么一个特性,"由简入奢易,由奢如简难"(据好 ...

  7. 【NOI2020】美食家(矩阵)

    Description 给定一张有向图,\(n\) 个顶点,\(m\) 条边.第 \(i\) 条边从 \(u_i\) 到 \(v_i\),走完该边的用时为 \(w_i\).每一个点有一个价值 \(c\ ...

  8. [XIN算法应用]NOI2020美食家

    XIN(\(updated 2021.6.4\)) 对于很多很多的题目,发现自己并不会之后,往往会直接冲上一个XIN队算法,然而,这样 \(\huge{\text{鲁莽}}\) 的行为只能获得 TLE ...

  9. BZOJ1691: [Usaco2007 Dec]挑剔的美食家

    传送门: 一句话题解:贪心+treap 好几天前刚学的treap,然后真到了考treap又写不出来,这么辣鸡还搞什么OI 先按$A_i$递减排序,然后把$C_i$也递减排序,然后用一个指针指向$M$序 ...

随机推荐

  1. 069 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 01 综合案例-数组移位-案例需求

    069 01 Android 零基础入门 01 Java基础语法 09 综合案例-数组移位 01 综合案例-数组移位-案例需求 本文知识点:综合案例-数组移位-案例需求 说明:因为时间紧张,本人写博客 ...

  2. puts()和gets()函数

    puts()和gets()函数 1. puts()函数 puts()函数用来向标准输出设备(屏幕)写字符串并换行, 其调用格式为: puts(s); 其中s为字符串变量(字符串数组名或字符串指针). ...

  3. RTKLIB的主要功能

    RTKLIB是全球导航卫星系统GNSS(global navigation satellite system)的标准&精密定位开源程序包,RTKLIB由日本东京海洋大学(Tokyo Unive ...

  4. 101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联——方案二

    101 01 Android 零基础入门 02 Java面向对象 03 综合案例(学生信息管理) 02 案例分析及实现 05 通过方法实现学生类与专业类关联--方案二 本文知识点:通过方法实现学生类与 ...

  5. 完全小白入门:python的下载和安装

    1. 打开官网www.python.org,选择Downloads

  6. Linux系统编程 —共享内存之mmap

    共享内存概念 共享内存是通信效率最高的IPC方式,因为进程可以直接读写内存,而无需进行数据的拷备.但是它没有自带同步机制,需要配合信号量等方式来进行同步. 共享内存被创建以后,同一块物理内存被映射到了 ...

  7. k8s的namespace一直Terminating的完美解决方案

    k8s的namespace一直Terminating的完美解决方案 在k8s集群中进行测试删除namespace是经常的事件,而为了方便操作,一般都是直接对整个名称空间进行删除操作. 相信道友们在进行 ...

  8. ansible-playbook-roles基本使用

    1. ansible-角色-roles基本使用  1.1) 创建roles目录结构 1 [root@test-1 ansible]# mkdir -p /ansible/roles/{common,n ...

  9. 多测师讲解接口测试 _理论基础知识001_高级讲师肖sir

    前言: 我们今天进入接口测试的学习! 今天学习的内容是偏向理论 接口理论 了解接口测试(1) 一.什么是接口测试? 接口统称api,即程序与程序之间的对接.交接.交互.是测试系统组件间接口的一种测试. ...

  10. Rust之路(3)——数据类型 下篇

    [未经书面同意,严禁转载] -- 2020-10-14 -- 架构是道,数据是术.道可道,非常道:术不名,不成术!道无常形,术却可循规. 学习与分析数据类型,最基本的方法就是搞清楚其存储原理,变量和对 ...