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 ...
随机推荐
- java_第一年_JDBC(1)
JDBC(Java Data Base Connectivity),用于实现java语言编程与数据库连接的API. 数据库驱动:应用程序并不能直接使用数据库,而需要通过相应的数据库驱动程序后再操作数据 ...
- 30分钟Maven入门到精通
Maven是近年来最流行的项目构建与管理工具.不仅简化了我们开发过程中对jar包依赖的导入,还对项目的清理.初始化.编译.测试.打包.集成测试.验证.部署和站点生成等所有构建过程进行了抽象和统一,方便 ...
- java中的进制转换
java中的进制转换及转换函数 转自:https://blog.csdn.net/V0218/article/details/74945203 Java的进制转换 进制转换原理 十进制 转 二进制: ...
- Java动态加载类
详见:https://blog.csdn.net/zai_xia/article/details/80026325 扩展:java反射机制与动态加载类 https://www.cnblogs.com/ ...
- pyinstaller打包总结
建立py打包文件 if __name__ == '__main__': from PyInstaller.__main__ import run #opts=['music.py','--path=C ...
- pycharm 激激活码
pycharm 激活码 [20191224亲测可用] http://lookdiv.com/neet/youd/codes.html
- 批量恢复zencart产品表所属分类master_categories_id为0的产品
批量恢复zencart产品表所属分类master_categories_id为0的产品 将下面代码保存为master_categories_id.php,上传到网站根目录运行即可,操作前先备份数据库 ...
- hdu 1003 最大连续子串
#include <bits/stdc++.h> #define PI acos(-1.0) #define mem(a,b) memset((a),b,sizeof(a)) #defin ...
- vue父组件调用子组件方法、父组件向子组件传值、子组件向父组件传值
一.父组件调用子组件方法 父组件代码 parent.vue <template> <div> <button @click="parentFun" ...
- [易学易懂系列|rustlang语言|零基础|快速入门|(4)|借用Borrowing]
[易学易懂系列|rustlang语言|零基础|快速入门|(4)] Borrowing 继续讲讲另一个重要的概念:借用(borrowing), 什么是借用? 我们先来看前一文章([易学易懂系列|rust ...