Atcoder ABC388F Dangerous Sugoroku 题解 [ 蓝 ] [ 矩阵加速 ] [ 状压矩乘 ] [ 模拟 ]
Dangerous Sugoroku:赛时写了矩乘 T 飞了,受到 sunkuangzheng 大佬的启发才知道要状压矩乘。
暴力矩乘思路
直接像过河那样写模拟细节非常多,于是考虑像美食家一样的思路,利用矩阵分段加速。
定义 \(dp_i\) 表示 \(i\) 能否到达,则有如下转移:
\]
因为 \(A,B\le 20\),所以可用状态非常少,就可以用矩阵优化了。
那么很显然就把段拆一下,然后直接跑矩乘就好了。这个做法甚至连 \(m=0,l_i-1=r_{i-1}\) 的细节都不用判。
代码如下,如果你真这么写了,会收获 TLE 和 WA 的好成绩!
下面这份暴力中 \(dp_i\) 表示 \(dp_i\) 的方案数,所以转移有所不同,本质还是和上面一样的。只要 \(dp_i>0\) 就能到达。
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
struct mat{
ull a[25][25];
mat(){memset(a,0,sizeof(a));}
mat operator*(const mat &x)const{
mat res;
for(int i=0;i<=20;i++)
{
for(int k=0;k<=20;k++)
{
ull l=a[i][k];
for(int j=0;j<=20;j++)
{
res.a[i][j]=(res.a[i][j]+l*x.a[k][j]);
}
}
}
return res;
}
}s,dp1,dp2;
mat qpow(mat x,ll k)
{
mat res;
for(int i=0;i<=20;i++)res.a[i][i]=1;
while(k>0)
{
if(k&1)res=res*x;
x=x*x;
k>>=1;
}
return res;
}
ll n,m,a,b,l[200005],r[200005];
int main()
{
//freopen("sample.in","r",stdin);
//freopen("sample.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>a>>b;
s.a[1][20]=1;
for(int i=1;i<=19;i++)dp1.a[i+1][i]=dp2.a[i+1][i]=1;
for(int i=20-a+1;i>=20-b+1;i--)dp1.a[i][20]=1;
r[0]=1;
for(int i=1;i<=m;i++)
{
cin>>l[i]>>r[i];
if(r[i]-l[i]+1>=21||l[i]==1)
{
cout<<"No";
return 0;
}
if(l[i]-r[i-1]-1>0)s=s*qpow(dp1,l[i]-r[i-1]-1);
if(r[i]-l[i]+1>0)s=s*qpow(dp2,r[i]-l[i]+1);
}
if(n+1-r[m]-1>0)s=s*qpow(dp1,n+1-r[m]-1);
if(s.a[1][20])cout<<"Yes";
else cout<<"No";
return 0;
}
原因是复杂度为 \(O(m\times 20^3 \log n)\),常数又大,无法通过。
优化矩乘
因为状态中只有 \(0\) 和 \(1\),每行每列的数又只有 \(20\) 个,考虑用状压与位运算去掉一个 \(20\)。
我们先看暴力的矩乘代码,再来考虑如何优化它。
struct mat{
ull a[25][25];
mat(){memset(a,0,sizeof(a));}
mat operator*(const mat &x)const{
mat res;
for(int i=0;i<=20;i++)
{
for(int k=0;k<=20;k++)
{
for(int j=0;j<=20;j++)
{
res.a[i][j]=(res.a[i][j]|(a[i][k]&x.a[k][j]));
}
}
}
return res;
}
}
可以发现,当 \(a_{i,k}=1\) 时,\(res_{i,j}\) 取决于 \(x_{i,j}\) 是否为 \(1\)。
因此,就可以省去循环 \(j\),当 \(a_{i,k}=1\) 时,直接让 \(res_i \gets res_i \vee x_k\) 即可。
时间复杂度 \(O(m\times 20^2 \log n)\),可以通过。
代码如下:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lc (p<<1)
#define rc ((p<<1)|1)
#define eb(x) emplace_back(x)
#define pb(x) push_back(x)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using pi=pair<int,int>;
struct mat{
ull a[25];
mat(){memset(a,0,sizeof(a));}
mat operator*(const mat &x)const{
mat res;
for(int i=0;i<=20;i++)
{
for(int k=0;k<=20;k++)
{
if((a[i]>>k)&1)res.a[i]=(res.a[i]|x.a[k]);
}
}
return res;
}
}s,dp1,dp2;
mat qpow(mat x,ll k)
{
mat res;
for(int i=0;i<=20;i++)res.a[i]=(1<<i);
while(k>0)
{
if(k&1)res=res*x;
x=x*x;
k>>=1;
}
return res;
}
ll n,m,a,b,l[200005],r[200005];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>a>>b;
s.a[1]=(1<<20);
for(int i=1;i<=19;i++)dp1.a[i+1]=dp2.a[i+1]=(1<<i);
for(int i=20-a+1;i>=20-b+1;i--)dp1.a[i]|=(1<<20);
r[0]=1;
for(int i=1;i<=m;i++)
{
cin>>l[i]>>r[i];
if(r[i]-l[i]+1>=21||l[i]==1)
{
cout<<"No";
return 0;
}
if(l[i]-r[i-1]-1>0)s=s*qpow(dp1,l[i]-r[i-1]-1);
if(r[i]-l[i]+1>0)s=s*qpow(dp2,r[i]-l[i]+1);
}
if(n+1-r[m]-1>0)s=s*qpow(dp1,n+1-r[m]-1);
if((s.a[1]>>20)&1)cout<<"Yes";
else cout<<"No";
return 0;
}
Atcoder ABC388F Dangerous Sugoroku 题解 [ 蓝 ] [ 矩阵加速 ] [ 状压矩乘 ] [ 模拟 ]的更多相关文章
- 【题解】P3959 宝藏 - 状压dp / dfs剪枝
P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的m 条道路和它们的长度. 小明决心亲自前往挖掘所有宝 ...
- Bzoj 3813 奇数国 题解 数论+线段树+状压
3813: 奇数国 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 748 Solved: 425[Submit][Status][Discuss] ...
- NOIp2016 D2T3 愤怒的小鸟【搜索】(网上题解正解是状压)
题目传送门 没啥别的想法,感觉就是搜索,经过原点的抛物线已知两个点就可以求出解析式,在还没有被打下来的两个猪之间随意配对,确定解析式之后标记在这个抛物线下被打下来的猪. 猪也可以单独用一个抛物线打下来 ...
- 【题解】P2831 愤怒的小鸟 - 状压dp
P2831愤怒的小鸟 题目描述 \(Kiana\) 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 \((0,0)\) 处,每次 \(Kiana\) 可以 ...
- 洛谷 P1939 矩阵加速(数列)
题意简述 \(a[1]=a[2]=a[3]=1\) \(a[x]=a[x−3]+a[x−1](x>3)\) 求a数列的第n项对1000000007取余的值. 题解思路 矩阵加速 设\[ F=\b ...
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
- BZOJ2004:[HNOI2010]Bus 公交线路(状压DP,矩阵乘法)
Description 小Z所在的城市有N个公交车站,排列在一条长(N-1)km的直线上,从左到右依次编号为1到N,相邻公交车站间的距离均为1km. 作为公交车线路的规划者,小Z调查了市民的需求,决定 ...
- 【KMP】【矩阵加速】【递推】洛谷 P3193 [HNOI2008]GT考试 题解
看出来矩阵加速也没看出来KMP…… 题目描述 阿申准备报名参加 GT 考试,准考证号为\(N\)位数\(X_1,X_2…X_n(0\le X_i\le9)\),他不希望准考证号上出现不吉利的数 ...
- 洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速$dp\&Floyd$)
洛谷P3502 [POI2010]CHO-Hamsters感想及题解(图论+字符串+矩阵加速\(dp\&Floyd\)) 标签:题解 阅读体验:https://zybuluo.com/Junl ...
- [模板][题解][Luogu1939]矩阵乘法加速递推(详解)
题目传送门 题目大意:计算数列a的第n项,其中: \[a[1] = a[2] = a[3] = 1\] \[a[i] = a[i-3] + a[i - 1]\] \[(n ≤ 2 \times 10^ ...
随机推荐
- 定时任务管理之qinglong
定时任务,是在日常开发需求中总会遇到的,我们往往会有一些简单的脚本工作,希望能够每小时或每天执行一次.当这类需求变得多起来后,这些零散的任务脚本就会变得难以管理,尤其是它们可能由不同的脚本语言编写而成 ...
- 理解Flink之三Transformation
Transformation 是 Flink操作的底层实现,无论是map还是Flatmap. DataStream类中包含两个变量: StreamExecutionEnvironment Transf ...
- 前后端数据传递之form-data
前情 最近在项目开发中,跟服务端连调发现接口一直报错,服务端一直提示是数据没有传,而通过浏览器控制台发现数据是有传的. 坑 服务通过postman自测是OK的.经过和服务端一起定位发现服务端只接收以f ...
- uni-app下载文件在ios下失败
标签: js uni-app 前情 uni-app是我很喜欢的跨平台框架,它能开发小程序,H5,APP(安卓/iOS),对前端开发很友好,自带的IDE让开发体验也很棒,公司项目就是主推uni-app. ...
- 【XML】Java创建XML文档
package example01; import org.w3c.dom.Document; import org.w3c.dom.Element; import javax.xml.parsers ...
- Netty有关
https://www.baeldung.com/tag/netty/ https://github.com/eugenp/tutorials https://stackoverflow.com/qu ...
- Qt采集本地摄像头推流成rtsp/rtmp(可网页播放/支持嵌入式linux)
一.功能特点 支持各种本地视频文件和网络视频文件. 支持各种网络视频流,网络摄像头,协议包括rtsp.rtmp.http. 支持将本地摄像头设备推流,可指定分辨率和帧率等. 支持将本地桌面推流,可指定 ...
- Qt编写地图综合应用5-自适应拉伸
一.前言 用过echart的人都会遇到一个问题,就算是代码中写了window.onresize = echart.resize,也只是横向自适应拉伸填充页面,垂直方向不会变化,除非指定高度才可以,这就 ...
- Windows上使用CMake GUI编译开源代码时,提示:cmake Could NOT find ZLIB (missing:ZLIB_LIBRARY)和Could NOT find PNG (missing: PNG_LIBRARY PNG_PNG_INCLUDE_DIR)的处理办法
有的时候就算在CMake GUI中配置完ZLIB_LIBRARY和PNG_LIBRARY和PNG_PNG_INCLUDE_DIR等相关路径,还是提示上述错误.原因还是由于编译某源码时遗漏了对第三方开源 ...
- 基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v8.0版已发布
关于MobileIMSDK MobileIMSDK 是一套专门为移动端开发的开源IM即时通讯框架,超轻量级.高度提炼,一套API优雅支持 UDP .TCP .WebSocket 三种协议,支持 iOS ...