[SHOI2013]超级跳马
题目描述
现有一个n 行m 列的棋盘,一只马欲从棋盘的左上角跳到右下角。每一步它向右跳奇数列,且跳到本行或相邻行。跳越期间,马不能离开棋盘。试求跳法种数mod 30011。
输入输出格式
输入格式:
仅有一行,包含两个正整数n, m,表示棋盘的规模。
输出格式:
仅有一行,包含一个整数,即跳法种数mod 30011。
输入输出样例
输入样例#1:
3 5
输出样例#1:
10
说明
对于10%的数据,1 ≤ n ≤ 10,2 ≤ m ≤ 10;
对于50%的数据,1 ≤ n ≤ 10,2 ≤ m ≤ 10^5;
对于80%的数据,1 ≤ n ≤ 10,2 ≤ m ≤ 10^9;
对于100%的数据,1 ≤ n ≤ 50,2 ≤ m ≤ 10^9。
题解
好久没写矩乘有点忘了
但是这种不难的题还是可以写出来的==
DP式子显然\(f[i][j] = (Sum[i-1][j]+Sum[i-1][j-1]+Sum[i-1][j+1])\)
那个\(Sum[i][j]\)表示的是第j行前i列的前缀和
然后这样不好做矩乘
可以用\(f[i][j]\)表示第j行前i列的前缀和
然后就是\(f[i][j] = f[i-2][j] + f[i-1][j] + f[i-1][j-1] + f[i-1][j+1]\)
但是这是个前缀和
所以\(Ans=f[m-1][n]+f[m-1][n-1]\)
这样就可以矩乘了
构造一个\((1 , n*2)\)的初始矩阵
前n个表示的是当前列的每一行的\(f[][]\)
后n个表示的是当前列的上一列的每一行的\(f[][]\)
然后转移矩阵就肥肠简单了
只需要把要转移的位置补上1就可以了
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
const int N = 105 ;
const int mod = 30011 ;
using namespace std ;
int n , m , E ;
int t[N][N] , Ans ;
struct Matrix {
int f[N][N] ;
inline Matrix () { memset(f , 0 , sizeof(f)) ; }
inline void Start() { for(int i = 1 ; i <= E ; i ++) f[i][i] = 1 ; }
inline friend Matrix operator * (Matrix a , Matrix b) {
Matrix temp ;
for(int i = 1 ; i <= E ; i ++)
for(int j = 1 ; j <= E ; j ++)
for(int k = 1 ; k <= E ; k ++)
temp.f[i][j] = (temp.f[i][j] + a.f[i][k] * b.f[k][j]) % mod ;
return temp ;
}
} st , b , Now ;
inline Matrix Fpw(Matrix Base , int k) {
Matrix temp ; temp.Start() ;
while(k) {
if(k & 1) temp = temp * Base ;
Base = Base * Base ; k >>= 1 ;
}
return temp ;
}
int main() {
cin >> n >> m ; t[1][1] = 1 ; E = (n << 1) ;
for(int i = 1 ; i <= n ; i ++) t[2][i] = (t[1][i] + t[1][i - 1] + t[1][i + 1]) % mod ;
if(m <= 3) { Ans = (t[m - 1][n] + t[m - 1][n - 1]) % mod ; printf("%d\n",Ans) ; return 0 ; }
for(int i = 1 ; i <= n ; i ++) st.f[1][i] = t[2][i] ;
for(int i = n + 1 ; i <= E ; i ++) st.f[1][i] = t[1][i - n] ;
for(int i = 1 ; i <= n ; i ++) {
b.f[i][i] = 1 ;
if(i != 1) b.f[i - 1][i] = 1 ;
if(i != n) b.f[i + 1][i] = 1 ;
b.f[i + n][i] = 1 ;
}
for(int i = n + 1 ; i <= E ; i ++) b.f[i - n][i] = 1 ;
Now = Fpw(b , m - 3) ; st = st * Now ;
Ans = (st.f[1][n] + st.f[1][n - 1]) % mod ;
cout << Ans << endl ;
return 0 ;
}
[SHOI2013]超级跳马的更多相关文章
- [BZOJ 4417][Shoi2013]超级跳马
4417: [Shoi2013]超级跳马 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 379 Solved: 230[Submit][Status ...
- 洛谷 P3990 [SHOI2013]超级跳马 解题报告
P3990 [SHOI2013]超级跳马 题目描述 现有一个\(n\) 行 \(m\) 列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘. ...
- [题解][SHOI2013]超级跳马 动态规划/递推式/矩阵快速幂优化
这道题... 让我见识了纪中的强大 这道题是来纪中第二天(7.2)做的,这么晚写题解是因为 我去学矩阵乘法啦啦啦啦啦对矩阵乘法一窍不通的童鞋戳链接啦 层层递推会TLE,正解矩阵快速幂 首先题意就是给你 ...
- BZOJ4417: [Shoi2013]超级跳马
Description 现有一个n行m列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘.例如,当n = 3, m = 10时,下图是一种可 ...
- 【BZOJ4417】: [Shoi2013]超级跳马
题目链接: 传送. 题解: 矩阵快速幂优化DP. 先考虑$nm^2$DP,设$f_{(i,j)}$表示从$1,1$到$i,j$的方案,显然这个方程和奇偶性有关,我们考虑某列的$i$同奇偶性的转移和奇偶 ...
- Luogu P3990 [SHOI2013]超级跳马
这道题还是一道比较不可做的矩阵题 首先我们先YY一个递推的算法:令f[i][j]表示走到第i行第j列时的方案数,那么有以下转移: f[i][j]=f[i-1][j-2*k+1]+f[i+1][j-2* ...
- 【bzoj4417】[Shoi2013]超级跳马 矩阵乘法
题目描述 现有一个n行m列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘.例如,当n = 3, m = 10时,下图是一种可行的跳法. ...
- P3990 [SHOI2013]超级跳马
传送门 首先不难设\(f[i][j]\)表示跳到\((i,j)\)的方案数,那么不难得到如下转移 \[f[i][j]=\sum\limits_{k=1}^{\frac n2}f[i-2k+1][j-1 ...
- BZOJ 4417 Luogu P3990 [SHOI2013]超级跳马 (DP、矩阵乘法)
题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=4417 (luogu)https://www.luogu.org/prob ...
随机推荐
- 洛谷P1186 玛丽卡
题目描述 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复. 因为她和他们不住在同一个城市,因此她开始准备她的长途旅行. 在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城 ...
- 2017-10-02-afternoon
T1 最大值(max) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有一本书,上面有很多有趣的OI问题.今天LYK看到了这么一道题目: 这里有一个长度 ...
- MongoDB小结07 - update【$addToSet & $each】
用$addToSet更新可以避免重复,将它与$each组合起来,可以一次性添加多条(就算后添加的值已存在也没有关系) db.user.update({"name":"co ...
- NTKO在线office控件使用实例
目录 1. NTKO在线office控件使用实例 1.1. 基础介绍 1.2. 基本原理 1.3. 实例 1.3.1. 打开.保存部分代码 1.3.2. 动态设值 1. NTKO在线office控件使 ...
- 条款一:仔细区别pointers 和 reference
1.一个reference必须总代表某个对象,没有所谓的null reference.如果你有一个变量,其目的是用来指向(代表)另一个对象,但是也有可能它不指向(代表)另一个对象,那么应该使用poin ...
- 玩转iOS开发 - 消息推送
消息推送
- Python学习系列之反射
反射的定义 根据字符串的形式去某个对象中操作成员 根据字符串的形式去某个对象中寻找成员 根据字符串的形式去某个对象中设置成员 根据字符串的形式去某个对象中删除成员 根据字符串的形式去某个对象中判断成员 ...
- 文件权限的获取,cmd命令:Takeown
takeown /f * /a /r /d y #强制将当前目录下的所有文件及文件夹.子文件夹下的所有者更改为管理员组(administrators)命令: cacls d:documents*.* ...
- C#——await与async实现多线程异步编程
曾经,我们也许用过Thread.在主线程运行的时候.新开还有一个新线程,来运行新方法. 今天看别人发给我的一段代码的时候发现了一个不认识的await,可是又感觉非常熟悉的样子,感觉是线程那块儿的东西, ...
- Jmeter技巧
Jmeter参数化的4种方法 用Jmeter测试时包含两种情况的参数,一种是在url中,一种是请求中需要发送的参数. URL中的参数,如:http://blog.da-fang.com/index.p ...