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^ ...
随机推荐
- vue之vuex使用
如图所示,它是一个程序里面的状态管理模式,它是集中式存储所有组件的状态的小仓库,并且保持我们存储的状态以一种可以预测的方式发生变化.对于可以预测,现在我不多做说明,相信在看完这篇文章之后,你就会有自己 ...
- elementUI中的级联选择器,默认赋值不起作用
今天遇到再使用element的级联选择器功能的时候,是多选,默认赋值不起作用. 后来查到是因为少了multiple属性,但是multiple属性要放在props绑定的对象中,而不是直接放在标签上 &l ...
- ssh之秘钥登陆
前提: 1. 秘钥的生成需要OpenSSL的支持, 需要自行进行安装 一. 新建用户 在root登陆状态中执行命令: useradd -m ssh-user # centosadduser ssh-u ...
- .net core想到哪写道哪之asp.net core的机密
我们往往需要在项目里使用一些机密数据,比如数据库的密码,再比如一些密钥.这些东西一般来说我们都会放到配置文件里. 但是这些东西是跟自己的账号相关的,我们在一些多人合作的项目中,尤其是开源项目肯定不能直 ...
- Asp.net MVC中的Http管道事件为什么要以Application_开头?
今天遇到一个问题,需要在API请求结束时,释放数据库链接,避免连接池被爆掉. 按照以往的经验,需要实现IHttpModule,具体不展开了. 但是实现了IHttpModule后,还得去web.conf ...
- Nuxt.js 应用中的 error 事件钩子
title: Nuxt.js 应用中的 error 事件钩子 date: 2024/12/3 updated: 2024/12/3 author: cmdragon excerpt: 在任何 Web ...
- GraphQL Part VIII: 使用一对多查询
今天,我们引入两个新的实体来处理客户与订单.客户与订单之间是一对多的关系,一个客户可以拥有一个或者多个订单,反过来,一个订单只能被某个客户所拥有. 可以按照 Engity Framework 的约定配 ...
- Excel 真的很强大之 Excel DDE 攻击
https://pentestlab.blog/2018/01/16/microsoft-office-dde-attacks/ =cmd|'/c calc.exe'!A1 =MSEXCEL|'\.. ...
- 【MyBatis】学习笔记15:通过分步查询解决一对多或多对多问题
目录 对象 SmbmsProvider.java SmbmsBill.java 接口 providerMapper.java orderMapper.java 映射文件 providerMapper. ...
- Qt编写可视化大屏电子看板系统16-标准柱状图
一.前言 标准柱状图是大屏系统中最常用的一种展示数据效果图,提供不同的柱子显示数据值,在QCustomPlot的基础上拓展了顶部显示对应的值,不同的柱子不同的颜色,同时还可以调用内置的触发报警颜色的机 ...