UPD 2021.4.9:修了个 typo,为啥写题解老出现 typo 啊(

Codeforces 题目传送门 & 洛谷题目传送门

这是一道 *2900 的 D1C,不过还是被我想出来了

u1s1 大概是这题用到的几个套路我都见过罢

首先注意到 \(k\) 很小,故考虑状压 \(dp\),\(dp_{i,s}\) 表示当前所有 pollywog 都在编号 \([i-k+1,i]\) 范围内的石头上,并且有且仅有编号 \(i-x+1,x\in s\) 的石头上有 pollywog。

转移还是比较显然的,如果 \(k\in s\),那么我们必须强制让这个当前位于 \(i-k+1\) 位置的 pollywog 跳 \(k\) 步,否则我们可以枚举一个青蛙并让它跳到编号为 \(i+1\) 的石头上,或者干脆 \(i+1\) 位置上不放 pollywog,也就是说:

  • \(dp_{i+1,s'}\leftarrow dp_{i,s}+c_k+a_{i+1},s'=\{x+1|x\in s\land x\ne k\}\cup\{1\}(k\in s)\)
  • \(dp_{i+1,s'}\leftarrow dp_{i,s}+c_d+a_{i+1},s'=\{x+1|x\in s\land x\ne d\}\cup\{1\}(k\notin s,d\in s)\)
  • \(dp_{i+1,s'}\leftarrow dp_{i,s}+c_k,s'=\{x+1|x\in s\}(k\notin s)\)

其中 \(c_i\) 为跳 \(i\) 格所需消耗的体力,\(a_i\) 为 \(i\) 所在的特殊格所额外消耗的体力(如果 \(i\) 不是特殊格则 \(a_i=0\))。

初始 \(dp_{x,\{1,2,\dots,x\}}=0\),答案为 \(dp_{n,\{1,2,\dots,x\}}\)。

考虑优化,注意到这个 \(n\) 很大但是这个转移呈规律性。故考虑矩阵优化 \(dp\),我们把转移方程用矩阵的形式表示出来,即我们总能找到一个矩阵 \(A\) 使得 \(A\times\begin{bmatrix}dp_{i,0}\\dp_{i,1}\\\dots\\dp_{i,2^k-1}\end{bmatrix}=\begin{bmatrix}dp_{i+1,0}\\dp_{i+1,1}\\\dots\\dp_{i+1,2^k-1}\end{bmatrix}\)(其中两个大小分别为 \(n\times m,m\times k\) 的矩阵 \(A,B\) 乘法得到的矩阵 \(C\) 为 \(n\times k\) 的矩阵,且 \(C_{i,j}=\min\limits_{l=1}^mA_{i,l}+B_{l,j}\))。那么如果没有什么特殊格子的限制的话,直接一遍矩阵快速幂就行了。

接下来考虑有特殊格子的情况,我们按照 CF576D 的套路将所有特殊格子按坐标排个序,显然一个特殊格子 \((x,y)\) 对 \(dp\) 值产生的影响就是令 \(\forall 1\in S,dp_{x,S}\leftarrow dp_{x,S}+y\)。故可以直接矩阵快速幂求出 \(dp_x\),然后就直接在 \(dp_x\) 上修改贡献即可。

这个算法的复杂度 \(\omega^3p\log n\) 的,其中 \(\omega=2^k\),无法通过。

考虑优化,注意到这个转移矩阵 \(A\) 是不会发生变化的,故考虑借鉴 P6772 的套路,而我们矩阵快速幂求出 \(dp_x\) 实质上是矩阵乘向量,单次乘法复杂度为 \(\omega^2\),故考虑预处理出 \(A^{2^k}\),这样可实现 \(\omega^3\log n\) 预处理,\(\omega^2p\log n\) 矩阵快速幂。

可是这样还是会炸啊……

这里还有第三个套路,就是对于合法的 \(dp_{i,S}\) 一定有 \(|S|=x\),故合法的状态最多 \(\binom{8}{4}=70\) 种,于是可以把所有合法的状态压缩成一个 \([1,70]\) 内的整数,这样矩阵大小就降到了 \(70\) 了。

时间复杂度 \(\omega^3\log n+\omega^2p\log n+\log p\),目前最优解 rk1

#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#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;
typedef unsigned int u32;
typedef unsigned long long u64;
namespace fastio{
#define FILE_SIZE 1<<23
char rbuf[FILE_SIZE],*p1=rbuf,*p2=rbuf,wbuf[FILE_SIZE],*p3=wbuf;
inline char getc(){return p1==p2&&(p2=(p1=rbuf)+fread(rbuf,1,FILE_SIZE,stdin),p1==p2)?-1:*p1++;}
inline void putc(char x){(*p3++=x);}
template<typename T> void read(T &x){
x=0;char c=getchar();T neg=0;
while(!isdigit(c)) neg|=!(c^'-'),c=getchar();
while(isdigit(c)) x=(x<<3)+(x<<1)+(c^48),c=getchar();
if(neg) x=(~x)+1;
}
template<typename T> void recursive_print(T x){if(!x) return;recursive_print(x/10);putc(x%10^48);}
template<typename T> void print(T x){if(!x) putc('0');if(x<0) putc('-'),x=~x+1;recursive_print(x);}
void print_final(){fwrite(wbuf,1,p3-wbuf,stdout);}
}
const int MAXK=8;
const int MAXP=25;
const int MAX_SIZ=70;
const int LOG_N=28;
const ll INF=0x3f3f3f3f3f3f3f3fll;
int x,k,n,p,c[MAXK+2];pii t[MAXP+2];
int st[MAX_SIZ+5],st_n=0,id[1<<MAXK];
struct mat{
int n,m;ll a[MAX_SIZ+5][MAX_SIZ+5];
mat(){}
mat(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;
}
mat operator *(const mat &rhs){
assert(m==rhs.n);mat res(n,rhs.m);
for(int i=1;i<=n;i++) for(int j=1;j<=rhs.m;j++)
for(int l=1;l<=m;l++) chkmin(res.a[i][j],a[i][l]+rhs.a[l][j]);
return res;
}
};
mat pw[LOG_N+2];
int main(){
scanf("%d%d%d%d",&x,&k,&n,&p);
for(int i=1;i<=k;i++) scanf("%d",&c[i]);
for(int i=1;i<=p;i++) scanf("%d%d",&t[i].fi,&t[i].se);
sort(t+1,t+p+1);
for(int i=0;i<(1<<k);i++) if(__builtin_popcount(i)==x){
st[++st_n]=i;id[i]=st_n;//printf("%d\n",i);
} mat trs(st_n,st_n);
for(int i=1;i<=st_n;i++){
if(st[i]>>(k-1)&1){
trs.a[id[((st[i]^(1<<(k-1)))<<1)|1]][i]=c[k];
} else {
for(int j=0;j<k;j++) if(st[i]>>j&1)
trs.a[id[((st[i]^(1<<j))<<1)|1]][i]=c[j+1];
trs.a[id[st[i]<<1]][i]=0;
}
}
// for(int i=1;i<=st_n;i++) for(int j=1;j<=st_n;j++)
// printf("%lld%c",trs.a[i][j],(j==st_n)?'\n':' ');
pw[0]=trs;
for(int i=1;i<=LOG_N;i++) pw[i]=pw[i-1]*pw[i-1];
int pre=x,init_msk=0;mat cur(st_n,1);
for(int i=0;i<x;i++) init_msk|=1<<i;
cur.a[id[init_msk]][1]=0;
for(int i=1;i<=p;i++){
int dif=t[i].fi-pre;
for(int j=LOG_N;~j;j--) if(dif>>j&1) cur=pw[j]*cur;
for(int j=1;j<=st_n;j++) if(st[j]&1) cur.a[j][1]+=t[i].se;
pre=t[i].fi;
}
int dif=n-pre;
for(int j=LOG_N;~j;j--) if(dif>>j&1) cur=pw[j]*cur;
printf("%lld\n",cur.a[id[init_msk]][1]);
// for(int i=1;i<=st_n;i++) printf("%d %lld\n",st[i],cur.a[i][1]);
return 0;
}

Codeforces 917C - Pollywog(状压 dp+矩阵优化)的更多相关文章

  1. BZOJ4000 [TJOI2015]棋盘 【状压dp + 矩阵优化】

    题目链接 BZOJ4000 题解 注意题目中的编号均从\(0\)开始= = \(m\)特别小,考虑状压 设\(f[i][s]\)为第\(i\)行为\(s\)的方案数 每个棋子能攻击的只有本行,上一行, ...

  2. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  3. 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂

    [题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...

  4. 【bzoj2004】[Hnoi2010]Bus 公交线路 状压dp+矩阵乘法

    题目描述 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定按下述规则设计 ...

  5. 【bzoj1097】[POI2007]旅游景点atr 状压dp+堆优化Dijkstra

    题目描述 FGD想从成都去上海旅游.在旅途中他希望经过一些城市并在那里欣赏风景,品尝风味小吃或者做其他的有趣的事情.经过这些城市的顺序不是完全随意的,比如说FGD不希望在刚吃过一顿大餐之后立刻去下一个 ...

  6. 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT

    题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...

  7. 2018.09.28 hdu5434 Peace small elephant(状压dp+矩阵快速幂)

    传送门 看到n的范围的时候吓了一跳,然后发现可以矩阵快速幂优化. 我们用类似于状压dp的方法构造(1(1(1<<m)∗(1m)*(1m)∗(1<<m)m)m)大小的矩阵. 然后 ...

  8. [Bzoj2004][Hnoi2010]Bus 公交线路(状压dp&&矩阵加速)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2004 看了很多大佬的博客才理解了这道题,菜到安详QAQ 在不考虑优化的情况下,先推$dp ...

  9. BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

    状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...

随机推荐

  1. cassandra表中主键的类型

    cassandra表中主键的类型及区分? 一.类型及区分 二.参考文章 一.类型及区分 Cassandra的4种Key Primary Key 主键 Composite Key,Compound Ke ...

  2. CSDN app分析

    项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) (北京航空航天大学 - 计算机学院) 这个作业的要求在哪里 个人博客作业-软件案例分析 我的教学班级 005 说说csd ...

  3. 攻防世界 web3.backup

    如果网站存在备份文件,常见的备份文件后缀名有:.git ..svn..swp..~..bak..bash_history..bkf尝试在URL后面,依次输入常见的文件备份扩展名. ip/index.p ...

  4. NOIP模拟85(多校18)

    前言 好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨). 然后我只知道 T1 的莓,确实挺惨... T1 莓良心 解题思路 首先答案只与 \(w\) 的和有关系,于是问题就 ...

  5. 基于屏幕空间的实时全局光照(Real-time Global Illumination Based On Screen Space)

    目录 Reflective Shadow Maps(RSM) RSM 的重要性采样 RSM 的应用与缺陷 Screen Space Ambient Occulsion(SSAO) SSAO Blur ...

  6. Codeforces Round #744 (Div. 3) G题题解

    淦,最后一道题没写出来,...还是我太菜了,不过这个题确实比较有趣. G. Minimal Coverage 简化题意:就是你处在坐标轴的0点上,给你一个序列\(a_i\),每次你可以选择向左走\(a ...

  7. zabbix 监控redis 挂掉自动重启 并发送企业微信

    1.创建redis监控项[配置]-[主机]-[监控项]-创建监控项,监控6379端口(注意关闭防火墙或者开启防火墙端口6379) redis配置文件设置允许任何地址监听: 添加监控项 2.创建redi ...

  8. CentOS7 安装oracle 11g (11.2.0.1.0)

    1.安装依赖: #yum -y install binutils compat-libcap1 compat-libstdc++-33 gcc gcc-c++ glibc glibc-devel ks ...

  9. ansible简介安装配置

    ansible简介 ansible是一款,自动化运维管理工具.顾名思义是用于批量去管理及安装服务及批量管理主机. ansible与saltstack对比 ansible优点:配置简单,部署容易除主管理 ...

  10. Linux常用命令和快捷键整理:(1)常用命令

    前言: Linux常用快捷键和基本命令整理,先上思维导图: 1.ls命令 就是list的缩写,通过ls 命令不仅可以查看linux文件夹包含的文件,而且可以查看文件权限(包括目录.文件夹.文件权限) ...