Codeforces917C. Pollywog
$n \leq 1e8$个石头,$x \leq 8$个蝌蚪一开始在最左边$x$个石子,要跳到最右的$x$个,每次只能最左边的蝌蚪跳一次,一个石头不能站两个蝌蚪,跳可以跳$1到k,x \leq k \leq 8$步,跳$i$步的代价是$cost_i$,还有$q \leq 25$个神奇石头,跳上去代价会$+w_i$,$w_i$可能为负数。问完成跳跃的最小代价。
不知道跳蝌蚪是什么操作只听过跳蛤,大概是变相膜?
好的严肃。从小数字$x$和$k$入手。由于每次只有最左的蝌蚪会跳,所以这$x$个蝌蚪一定每时每刻都在某连续的$k$个石头上。记这$k$个石头最左的那个(不一定上面有蝌蚪)为$i$,那么$i$处右边$k$个石子上的蝌蚪状态可以用二进制表示,最多是$C_8^4=70$个状态,挺小。这样就可以做转移了,转移复杂度是$C_k^x*k$,再乘个$n$直接爆炸。不过我们来看这个转移,$dp(i,j)=dp(i-1,k)+cost_t$,想到啥了?走若干步的最短路!这是可以用矩乘优化的,于是在不考虑$q$时,可以做$log_2n*(C_k^x)^3$的$dp$。
然后来看$q$。一块神奇石头影响了$k$块地(di)的(de)转移,因此最多会有$q*k$块地受影响,挺小,矩乘到这些地段时停住,暴力转移。最终复杂度$log_2n*(C_k^x)^3+qk^2C_k^x$。
//#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
//#include<map>
#include<math.h>
//#include<time.h>
//#include<complex>
#include<algorithm>
using namespace std; int X,K,n,m,q;
#define LL long long
const LL inf=1e18;
struct Mat
{
LL a[][];
Mat() {for (int i=;i<=;i++) for (int j=;j<=;j++) a[i][j]=inf;}
Mat operator * (const Mat &b)
{
Mat ans;
for (int k=;k<=m;k++)
for (int i=;i<=m;i++)
for (int j=;j<=m;j++)
ans.a[i][j]=min(ans.a[i][j],a[i][k]+b.a[k][j]);
return ans;
}
}base,f; Mat pow(Mat a,int b)
{
Mat ans,tmp=a; for (int i=;i<=m;i++) ans.a[i][i]=;
while (b)
{
if (b&) ans=ans*tmp;
tmp=tmp*tmp; b>>=;
}
return ans;
} int state[],ls,who[];
struct Ran{int l,r;}qq[],ran[]; int len;
LL g[],h[];int cost[];
struct Block{int pos,w;}ww[];
bool cmpww(const Block &a,const Block &b) {return a.pos<b.pos;}
struct Hash
{
int first[],le; struct Edge{int to,v,next;}edge[];
Hash() {le=;}
void insert(int x,int y) {int h=x%; Edge &e=edge[le]; e.to=x; e.v=y; e.next=first[h]; first[h]=le++;}
int find(int x) {int h=x%; for (int i=first[h];i;i=edge[i].next) if (edge[i].to==x) return edge[i].v; return -2e9;}
}ha; int main()
{
scanf("%d%d%d%d",&X,&K,&n,&q);
for (int i=;i<=K;i++) scanf("%d",&cost[i]);
for (int i=;i<=q;i++) scanf("%d%d",&ww[i].pos,&ww[i].w); sort(ww+,ww++q,cmpww);
LL ans=; for (int &i=q;i;i--) if (ww[i].pos>=n-X+) ans+=ww[i].w; else break;
for (int i=;i<=q;i++) ha.insert(ww[i].pos,ww[i].w);
for (int i=;i<=q;i++) qq[i].l=max(ww[i].pos-K,),qq[i].r=ww[i].pos;
len=; for (int i=;i<=q;i++)
{
if (len && qq[i].l<=ran[len].r+) ran[len].r=qq[i].r;
else len++,ran[len].l=qq[i].l,ran[len].r=qq[i].r;
}
ls=; for (int i=;i<(<<K);i++)
{
int cnt=;
for (int j=;j<K;j++) if ((i>>j)&) cnt++;
if (cnt==X) ls++,state[i]=ls,who[ls]=i;
} m=ls;
for (int i=;i<=ls;i++)
{
int s=who[i]>>;
if ((who[i]&)==) base.a[i][state[s]]=;
else for (int j=;j<=K;j++) if (((s>>(j-))&)==) base.a[i][state[s|(<<(j-))]]=cost[j];
}
f.a[][]=; ran[].r=;
for (int i=;i<=len;i++)
{
f=f*pow(base,ran[i].l-ran[i-].r-);
for (int j=;j<=ls;j++) g[j]=f.a[][j];
for (int j=ran[i].l;j<=ran[i].r;j++)
{
for (int k=;k<=ls;k++) h[k]=inf;
for (int k=;k<=ls;k++)
{
int s=who[k]>>;
if ((who[k]&)==) h[state[s]]=min(h[state[s]],g[k]);
else for (int l=,tmp;l<=K;l++) if (((s>>(l-))&)==)
{
int ns=s|(<<(l-));
if ((tmp=ha.find(j+l-))!=-2e9) h[state[ns]]=min(h[state[ns]],g[k]+cost[l]+tmp);
else h[state[ns]]=min(h[state[ns]],g[k]+cost[l]);
}
}
for (int k=;k<=ls;k++) g[k]=h[k];
}
for (int j=;j<=ls;j++) f.a[][j]=g[j];
}
f=f*pow(base,n-X+-ran[len].r);
printf("%lld\n",ans+f.a[][]);
return ;
}
Codeforces917C. Pollywog的更多相关文章
- CF917C Pollywog —— 状压DP + 矩乘优化
C. Pollywog 题目描述 原题题目链接.题目大意为:有$x$只蝌蚪,在$n$个石头中的最左端的$x$个石头上,这$n$个石头是在同一直线上的.每一次只能最左边的一个蝌蚪进行跳跃,并且只能跳$1 ...
- Codeforces 917C - Pollywog(状压 dp+矩阵优化)
UPD 2021.4.9:修了个 typo,为啥写题解老出现 typo 啊( Codeforces 题目传送门 & 洛谷题目传送门 这是一道 *2900 的 D1C,不过还是被我想出来了 u1 ...
- Pollywog CodeForces - 917C (状压)
链接 大意: 一共n个格子, 初始$x$只蝌蚪在前$x$个格子, 每次最左侧的蝌蚪向前跳, 跳跃距离在范围[1,k], 并且每只蝌蚪跳跃都有一定花费, 有$q$个格子上有石头, 若有蝌蚪跳到某块石头上 ...
随机推荐
- checkbox:全选、全不选、单选(慕课网题目)
任务 1.在第27行处补充完整,实现当点击"全选"按钮时,将选中所有的复选项. 提示:document.getElementsByTagName("input" ...
- spring 常见的注解
spring中的注解都必须在配置文件中进行如下的配置: <context:component-scan base-package="com.shanjin.oxm.service.im ...
- SQLite概述
SQLite概述 这个教程帮助您理解SQLite是什么,它如何不同于SQL,为什么它是必要的和它的方式处理应用程序数据库. SQLite是一个库,实现了一个独立的软件,serverless zer ...
- 嵌入式ARM开发板学习方法步骤
嵌入式开发就是指在嵌入式操作系统下进行开发,一般常用的系统有linux,android. 平台:Cortex-A9开发板 嵌入式技术学习如何入手,从何学起呢, 以下内容简单介绍嵌入式开发的学习步骤及如 ...
- Android Studio 中文件查询方法总结
搜索单词 Windows: Ctrl + F Mac : Cmd + F 会在当前激活的文件上查询输入的关键字,以高亮显示 跳转行 Windows: Ctrl + L Mac : Cmd + ...
- 升级或者重装Discuz! 版本后 QQ互联英文乱码显示的正确解决方法
升级Discuz! X3版本QQ互联英文乱码!connect_viewthread_share_to_qq! 目前Discuz!论坛上 最简单的解决方法: 第一步:后台----->站长---- ...
- 1+1/2+1/3+...+1/n为素数的证明
我们考虑不大于 n的最大的2 的幂 2^k. 令 有 其中 a/b是剩下的所有的项的和,由于乘以了最大的 2的幂,所以剩下的所有项的分母都是奇数,故而 b是奇数.如果 m是整数,那么就会导致等式右边的 ...
- 如何快速上手基础的CSS3动画
前言 说起CSS3动画,就必须说说 transform,translate,transition,animation这4个属性,transform主要定义元素的动作,比如旋转.倾斜.位移等,trans ...
- 暑假集训 || LCA && RMQ
LCA定义为对于一颗树 树上两个点的最近公共祖先 一.Tarjan求LCA(离线方法 https://blog.csdn.net/lw277232240/article/details/7701751 ...
- treeTable的使用(ajax异步获取数据,动态渲染treeTable)
一.展示效果(treetable基本样式https://www.cnblogs.com/shuihanxiao/p/10413454.html) 二.html文件(若一个页面又多个treetable, ...