BZOJ 4417 Luogu P3990 [SHOI2013]超级跳马 (DP、矩阵乘法)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4417
(luogu)https://www.luogu.org/problemnew/show/P3990
题解: 一看就是矩乘优化dp.
每次跳奇数列?那么我们可以将列两两分组,以两列为一组作为矩阵要记录的状态。一个元素位于组内第一列说明它不可能再跳到这一组的第二列(为了避免算重)。转移矩阵的构造见代码。
那么我们用矩阵来表示转移方程: 设向量\(F[i]\)表示状态,\(A\)表示转移矩阵,\(F[i]=\sum^{i-1}_{j=1}F[j]\times A\)
作差分,\(F[i]-F[i-1]=F[i-1]\times A\), \(F[i]=F[i-1]\times (A+I)\)
注意这个递推式成立的条件是\(i\ge 3\), 即必须预处理出\(F[2]\)的值而不可以通过\(F[1]\)得出(想一想,为什么)。
代码
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
#include<iostream>
#define llong long long
using namespace std;
inline int read()
{
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=0;
for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
if(f) return x;
return -x;
}
const int P = 30011;
const int N = 50;
struct Matrix
{
int n;
llong a[(N<<1)+3][(N<<1)+3];
void output() {for(int i=1; i<=n; i++) {for(int j=1; j<=n; j++) printf("%lld ",a[i][j]); puts("");}}
void clear(int _n) {n = _n; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) a[i][j] = 0ll;}
void unitize() {for(int i=1; i<=n; i++) a[i][i] = 1ll;}
Matrix operator *(const Matrix &arg) const
{
Matrix ret; ret.clear(n);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
for(int k=1; k<=n; k++)
{
ret.a[i][k] = (ret.a[i][k]+a[i][j]*arg.a[j][k])%P;
}
}
}
return ret;
}
} trans,cur,ans;
int n;
llong m;
void mquickpow(llong y)
{
cur = trans;
for(int i=0; y; i++)
{
if(y&(1ll<<i)) {y-=(1ll<<i); ans = ans*cur;}
cur = cur*cur;
}
}
int main()
{
scanf("%d%lld",&n,&m);
trans.clear(n<<1); cur.clear(n<<1); ans.clear(n<<1);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
if(j>=i-1 && j<=i+1)
{
trans.a[i][j+n]++;
trans.a[i+n][j]++;
}
}
}
for(int i=1; i<=n+n; i++)
{
for(int j=1; j<=n; j++)
{
for(int k=1; k<=n; k++)
{
if(k>=j-1 && k<=j+1)
{
trans.a[i][k+n] += trans.a[i][j];
}
}
}
}
ans = trans;
for(int i=1; i<=n+n; i++) trans.a[i][i]++;
mquickpow((m-3)>>1);
if(m&1) printf("%lld\n",(ans.a[1][n]+ans.a[n+1][n]+ans.a[n+2][n])%P);
else printf("%lld\n",(ans.a[1][n+n]+ans.a[n+1][n+n]+ans.a[n+2][n+n])%P);
return 0;
}
BZOJ 4417 Luogu P3990 [SHOI2013]超级跳马 (DP、矩阵乘法)的更多相关文章
- Luogu P3990 [SHOI2013]超级跳马
这道题还是一道比较不可做的矩阵题 首先我们先YY一个递推的算法:令f[i][j]表示走到第i行第j列时的方案数,那么有以下转移: f[i][j]=f[i-1][j-2*k+1]+f[i+1][j-2* ...
- 洛谷 P3990 [SHOI2013]超级跳马 解题报告
P3990 [SHOI2013]超级跳马 题目描述 现有一个\(n\) 行 \(m\) 列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘. ...
- 【BZOJ 3326】[Scoi2013]数数 数位dp+矩阵乘法优化
挺好的数位dp……先说一下我个人的做法:经过观察,发现这题按照以往的思路从后往前递增,不怎么好推,然后我就大胆猜想,从前往后推,发现很好推啊,维护四个变量,从开始位置到现在有了i个数 f[i]:所有数 ...
- P3990 [SHOI2013]超级跳马
传送门 首先不难设\(f[i][j]\)表示跳到\((i,j)\)的方案数,那么不难得到如下转移 \[f[i][j]=\sum\limits_{k=1}^{\frac n2}f[i-2k+1][j-1 ...
- [bzoj4417] [洛谷P3990] [Shoi2013] 超级跳马
Description 现有一个n行m列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘.例如,当n = 3, m = 10时,下图是一种可 ...
- 【BZOJ 2323】 2323: [ZJOI2011]细胞 (DP+矩阵乘法+快速幂*)
2323: [ZJOI2011]细胞 Description 2222年,人类在银河系外的某颗星球上发现了生命,并且携带了一个细胞回到了地球.经过反复研究,人类已经完全掌握了这类细胞的发展规律: 这种 ...
- 【BZOJ】1009: [HNOI2008]GT考试(dp+矩阵乘法+kmp+神题)
http://www.lydsy.com/JudgeOnline/problem.php?id=1009 好神的题orzzzzzzzzzz 首先我是连递推方程都想不出的人...一直想用组合来搞..看来 ...
- bzoj 4818: [Sdoi2017]序列计数【容斥原理+dp+矩阵乘法】
被空间卡的好惨啊---- 参考:http://blog.csdn.net/coldef/article/details/70305596 容斥,\( ans=ans_{没有限制}-ans{没有质数} ...
- [BZOJ 4417][Shoi2013]超级跳马
4417: [Shoi2013]超级跳马 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 379 Solved: 230[Submit][Status ...
随机推荐
- win10+vs2013+pcl1.8.0(x86) 环境配置遇到的各种小问题解决
1.PCL提供了各自的PDB调试文件(解压后放入pcl安装目录的bin下) 2.OpenNI的安装需同其余在pcl第三方库文件夹下 3.添加附加依赖项的.lib文件请按照网上对应版本添加,另外需要每行 ...
- Nginx与PHP如何协同工作
要说Nginx与PHP如何协同工作,首先得说CGI和FastCGI两个协议. CGI是Web Server与后台语言交互的协议,有了这个协议,开发者可以使用任何语言处理Web Server发来的请求, ...
- Spark RDD理解-总结
1.spark是什么 快速.通用.可扩展的分布式计算引擎. 2. 弹性分布式数据集RDD RDD(Resilient Distributed Dataset),是Spark中最基本的数据抽象结构,表示 ...
- GitHub编辑README.md
一.标题 等级表示法(六级): #一级标题 ##二级标题 ###三级标题 ####四级标题 #####五级标题 ######六级标题 一级标题/大标题(文本下面加上等于号): 大标题 === 二级标题 ...
- 腾讯万亿级分布式消息中间件TubeMQ正式开源
TubeMQ是腾讯在2013年自研的分布式消息中间件系统,专注服务大数据场景下海量数据的高性能存储和传输,经过近7年上万亿的海量数据沉淀,目前日均接入量超过25万亿条.较之于众多明星的开源MQ组件,T ...
- Java学习:通过Scanner读取文件
Scanner不仅能够读取用户的键盘输入,还可以读取文件输入. 需要在创建Scanner对象的时候传入一个File对象作为参数.代码如下: import java.util.Scanner; impo ...
- jqery实现10X10的表格,双击消失
<script type="text/javascript"> $(document).ready(function(){ //循环拼接html s="&qu ...
- js 学习一 猜数字游戏
知识点 js 操作元素 增 (document.createElement(),document.body.appendChild()), 删(parentNode.removeChild()) ,改 ...
- AT&T推出云5G网络开源工具Airship
导读 AT&T新推出的云5G网络依赖于一个名为“Airship”的开源供应工具,该工具在周一发布了第一个版本. AT&T负责网络云的副总裁Amy Wheelus告诉LightReadi ...
- mysql之innodb存储引擎
mysql之innodb存储引擎 innodb和myisam区别 1>.InnoDB支持事物,而MyISAM不支持事物 2>.InnoDB支持行级锁,而MyISAM支持表级锁 3>. ...