传送门: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. java安全编码指南之:方法编写指南

    目录 简介 不要在构造函数中调用可以被重写的方法 不要在clone()方法中调用可重写的方法 重写equals()方法 hashCode和equals compareTo方法的实现 简介 java程序 ...

  2. Java知识系统回顾整理01基础03变量04类型转换

    一.不同类型之间的数据可以互相转换,但是要满足一定的规则 二.数据类型转换规则 转换规则如图所示  精度高的数据类型就像容量大的杯子,可以放更大的数据 精度低的数据类型就像容量小的杯子,只能放更小的数 ...

  3. C++ CComboBox控件详解

    转载:http://blog.sina.com.cn/s/blog_46d93f190100m395.html C++ CComboBox控件详解 (2010-09-14 14:03:44) 转载▼ ...

  4. JavaScript判断字符串中出现次数最多的字符,并统计其次数

    要求: 输出一个给定字符串``中出现次数最多的字符,并统计其次数. 实现思路: 利用charA()遍历这个字符串 把每个字符都存储给对象,如果对象没有该属性,就先幅值为1,如果存在了就+1 遍历对象, ...

  5. 初学者的Android移植:在Debian上建立一个稳定的构建环境

    介绍 通过在chrooted环境中设置开发环境,避免依赖冲突和沙箱您的Android开发从您的Debian GNU/Linux系统.这是为通配符类别准备的,因为从源代码构建Android似乎没有在其他 ...

  6. K8S-kubeadm-集群证书续签

    ETCD证书 自签证书颁发机构(CA) ca.crt ca.key etcd集群中相互通信事业的客户端证书 peer.crt peer.key pod中定义Liveness探针事业的客户端证书 hea ...

  7. golang常用库:配置文件解析库-viper使用

    一.viper简介 viper 配置解析库,是由大神 Steve Francia 开发,他在google领导着 golang 的产品开发,他也是 gohugo.io 的创始人之一,命令行解析库 cob ...

  8. Linux设备驱动中的阻塞和非阻塞I/O <转载>

    Green 博客园 首页 新随笔 联系 订阅 管理 Linux设备驱动中的阻塞和非阻塞I/O   [基本概念] 1.阻塞 阻塞操作是指在执行设备操作时,托不能获得资源,则挂起进程直到满足操作所需的条件 ...

  9. mapbox处理中文标注不能换行问题

    mapbox的换行侧率是根据空格进行的,因为中文中没有设置空格,因此换行不起作用. 解决方法:在node_modules\ol-mapbox-style\util.js  60行添加下列代码: let ...

  10. Windows下CertUtil校验和编码文件

    目录 前言 CertUtil计算文件hash 计算MD2 计算MD4 计算MD5 计算SHA1 计算SHA256 计算SHA384 计算SHA512 文件base64编码 文件base64解码 文件h ...