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. netty系列之:netty对http2消息的封装

    目录 简介 http2消息的结构 netty对http2的封装 Http2Stream Http2Frame 总结 简介 无论是什么协议,如果要真正被使用的话,需要将该协议转换成为对应的语言才好真正的 ...

  2. JAVA复习总体大纲

    1 java基础. [1].变量--- 数据类型 变量名=值; 数据类型: 1.基本数据类型. byte[1字节] short[2字节] int[4字节] long[8字节] float[4字节] d ...

  3. 写了10000条Airtest截图脚本总结出来的截图经验,赶紧收藏!

    前言 今天想先给大家分享1个小白用户的Airtest从入门到放弃的故事: 小A是一个自动化的小白,在逛测试论坛的时候,偶然间发现了Airtest这个基于图像识别的UI自动化框架. 出于好奇,小A试用了 ...

  4. AIApe问答机器人项目Scrum Meeting博客汇总

    荡起双桨 Scrum Meeting 博客汇总 一.Alpha阶段 AIApe问答机器人Scrum Meeting 4.23 AIApe问答机器人Scrum Meeting 4.25 AIApe问答机 ...

  5. 用STM32内置的高速ADC实现简易示波器

    做一个数字采样示波器一直是我长久以来的愿望,不过毕竟这个目标难度比较大,涉及的方面实在太多,模拟前端电路.高速ADC.单片机.CPLD/FPGA.通讯.上位机程序.数据处理等等,不是一下子就能成的,慢 ...

  6. Register Abstraction(9)

    This post will explain how to use the UVM Register Abstraction Layer (RAL) to generate register tran ...

  7. UVA 10004 Bicoloring(DFS染色)

    题意: 给N个点构成的无环无向图,并且保证所有点对都是连通的. 给每个点染色,要么染成黑要么染成白.问是否存在染色方案使得所有有边相连的点对颜色一定不一样. 是输出 BICOLORABLE 否则输出 ...

  8. poj 3041 Asteroids(最小点覆盖)

    题意: N*N的矩阵,有K个敌人,坐标分别是(C1,C1),.....,(Rk,Ck). 有一个武器,每发射一次,可消掉某行或某列上的所有的敌人. 问消灭所有敌人最少需要多少发. 思路: 二分建图:左 ...

  9. 什么是 Webhook?

    1. 什么是 Webhook? Webhook 是一个 API 概念,是微服务 API 的使用范式之一,也被成为反向 API,即前端不主动发送请求,完全由后端推送:举个常用例子,比如你的好友发了一条朋 ...

  10. Java测试开发--JSONPath、JSONArray、JSONObject使用(十)

    一.Maven项目,pom.xml文件中导入 <dependency> <groupId>com.alibaba</groupId> <artifactId& ...