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$个格子上有石头, 若有蝌蚪跳到某块石头上 ...
随机推荐
- AJPFX总结java InputStream读取数据问题
1. 关于InputStream.read() 在从数据流里读取数据时,为图简单,经常用InputStream.read()方法.这个方法是从流里每次只读取读取一个字节,效率会非常低. ...
- pageHelper分页插件失效问题
在bootstrap中引用pageHelper进行页面分页<dependency><groupId>com.github.pagehelper</groupId>& ...
- mySQL 从删库到跑路
问题: 使用python实现load data infile ...向mySQL中导入数据.虽然成功执行但是数据库中没增加记录. 解决: zz的我execute之后没有commit.
- C# 移动开发(Xamarin.Form) Plugin.BLE 蓝牙连接
随着Xamarin.Form项目接近尾声,仔细一算才发现过来大半年时间了. 期间除了刚开始有闲情写写,现在总算有空来总结一下了. 来先说 Plugin.BLE (https://github.com/ ...
- SAP CRM点了附件的超链接后报错的处理方式
SAP CRM系统里,点击了附件的这些超链接后,如果是文本文件,会在浏览器里打开.如果是其他类型的文件,会弹出下载对话框. 然而最近我工作时遇到一个问题,点击超链接后,总是弹出Logon failed ...
- 如何用Chrome自带的截屏功能截取超过一个屏幕的网页
提升程序员工作效率的工具/技巧推荐系列 推荐一个功能强大的文件搜索工具SearchMyFiles 介绍一个好用的免费流程图和UML绘制软件-Diagram Designer 介绍Windows任务管理 ...
- docker使用阿里云镜像加速器(属于自己的专属加速器)
https://cr.console.aliyun.com/cn-shanghai/mirrors
- 汇编2.汇编版本的helloworld
寻址方式 立即数寻址 寄存器寻址 存储器寻址 直接寻址 : mov ax, [ 01000h ]; 直接在[]内给出一个内存地址 寄存器间接寻址: mov ax ,[si]; 在[]以寄存器的值给出内 ...
- DROP CONVERSION - 删除一个用户定义的编码转换
SYNOPSIS DROP CONVERSION name [ CASCADE | RESTRICT ] DESCRIPTION 描述 DROP CONVERSION 删除一个以前定义的编码转换. 要 ...
- python数据类型常用内置函数之字符串
1.strip, lstrip, rstrip x = ' jiahuifeng ' print(x.strip(' ')) print(x.lstrip(' ')) print(x.rstrip(' ...