Warcraft III 守望者的烦恼

背景

守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她传送到后面的监狱内查看,她比较懒,一般不查看完所有的监狱,只是从入口进入,然后再从出口出来就算完成任务了。

描述

头脑并不发达的warden最近在思考一个问题,她的闪烁技能是可以升级的,k级的闪烁技能最多可以向前移动k个监狱,一共有n个监狱要视察,她从入口进去,一路上有n个监狱,而且不会往回走,当然她并不用每个监狱都视察,但是她最后一定要到第n个监狱里去,因为监狱的出口在那里,但是她并不一定要到第1个监狱。

守望者warden现在想知道,她在拥有k级闪烁技能时视察n个监狱一共有多少种方案?

格式

输入格式

第一行是闪烁技能的等级k(1<=k<=10)

第二行是监狱的个数n(1<=n<=2^31-1)

输出格式

由于方案个数会很多,所以输出它 mod 7777777后的结果就行了

样例1

样例输入1

2

4

样例输出1

5

限制

各个测试点1s

提示

把监狱编号1 2 3 4,闪烁技能为2级,

一共有5种方案

→1→2→3→4

→2→3→4

→2→4

→1→3→4

→1→2→4

小提示:建议用int64,否则可能会溢出

这道题我们可以先考虑k=2的情况,发现其实此题的主要内容就是爬楼梯(k为最多爬多少步,n为有n阶楼梯)。所以在k=2时整个解排出来便是一个裴波那契数列,递推式为\(f_{n}=f_{n-1}+f_{n-2}\)。那么扩展到闪烁步数最大为k的情况,不难发现递推式便为\(f_{n}=f_{n-1}+f_{n-2}+f_{n-3}+...+f_{n-k}\)。

这里有一个初始化的问题让我思考了一段时间,这里阐述一下。如果k是小于n的,那么总的方案数会是多少。不难发现在\(k>n\)时,你最多一次只能爬n步,而不能爬k步,所以在\(k>n\)时,其实方案数就是\(f_{n}\),也就是\(f_{n}=f_{n-1}+f_{n-2}+...+f_{0}\)。

现在来考虑矩阵加速,方法类似于裴波那契数列的构造方法,具体请看此篇博客:https://blog.csdn.net/weixin_44049566/article/details/88946702

这里因为矩阵的阶数随k而定,所以可以使用循环来构造,类似于如下代码:

void pre1(int k) {
n=m=k;
for(int i=1;i<=k-1;i++) c[i+1][i]=1;
for(int i=1;i<=k;i++) c[i][k]=1;
}

加速矩阵构造出来类似于这样:

\(\begin{bmatrix}
& 0 & 0 & ... &0 \\
& 1 & 0& ... & 0\\
& 0 & 1& ... & 0\\
& ... & ... &... & ...\\
& 0 & 0& ... &1
\end{bmatrix}\)*\(\begin{bmatrix}
& f_{1}&f_{2}&...&f_{k}\end{bmatrix}\)

代码

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std; #define N 20
#define LL long long
#define MOD 7777777 LL k,n; struct Matrix {
LL n,m,c[N][N];
Matrix() { memset(c,0,sizeof(c)); };
void _read() {
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%lld",&c[i][j]);
}
Matrix operator * (const Matrix& a) {
Matrix r;
r.n=n;r.m=a.m;
for(int i=1;i<=r.n;i++)
for(int j=1;j<=r.m;j++)
for(int k=1;k<=m;k++)
r.c[i][j]= (r.c[i][j]+ (c[i][k] * a.c[k][j])%MOD)%MOD;
return r;
}
void _print() {
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
if(j!=1) cout<<" ";
cout<<c[i][j];
}
if(i!=n) puts("");
}
}
void pre1(int k) {
n=m=k;
for(int i=1;i<=k-1;i++) c[i+1][i]=1;
for(int i=1;i<=k;i++) c[i][k]=1;
}
void pre2(int k) {
n=1,m=k;
c[1][0]=c[1][1]=1;
for(int i=2;i<=k;i++)
for(int j=i-1;j>=0;j--)
c[1][i]+=c[1][j];
}
Matrix _power(int indexx) {
Matrix tmp,sum;tmp.pre1(k);
for(int i=1;i<=k;i++) sum.c[i][i]=1;sum.m=sum.n=k;
while(indexx>0) {
if(indexx&1) sum=sum*tmp;
tmp=tmp*tmp;
indexx/=2;
}
return sum;
} }A,B; int main() {
cin>>k>>n;
A.pre2(k);
B.pre1(k);
B=B._power(n-k);
A=A*B;
cout<<A.c[1][k];
}

C++矩阵加速经典题目:Warcraft III 守望者的烦恼 [vijos 1067]的更多相关文章

  1. [矩阵十题第七题]vijos 1067 Warcraft III 守望者的烦恼 -矩阵快速幂

    背景 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她传送到后面的监狱内查看,她比较懒,一般不查看 ...

  2. 矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)

    https://www.vijos.org/p/1067 非常easy推出递推式f[n] = f[n-1]+f[n-2]+......+f[n-k]. 构造矩阵的方法:构造一个k*k的矩阵.当中右上角 ...

  3. vijos 1067 Warcraft III 守望者的烦恼 矩阵

    题目链接 我们可以很容易的推出dp的式子, dp[i] = sigma(j : 1 to k) dp[i-j]. 但是n太大了, 没有办法直接算, 所以我们构造一个矩阵, 然后快速幂就好了. 就像这样 ...

  4. VOJ 1067 Warcraft III 守望者的烦恼 (矩阵高速功率+dp)

    主题链接 明显的 dp[n] = dp[n-k] + dp[n-k+1] + ... +dp[n-1]; 然后要用矩阵来优化后面的状态转移. 也就是矩阵 0 1 0 0    a     b 0 0 ...

  5. [Vijos1067]Warcraft III 守望者的烦恼(DP + 矩阵优化)

    传送门 可知 f[i] = f[i - 1] + f[i - 2] + ... + f[i - k] 直接矩阵优化就好了 #include <cstdio> #include <cs ...

  6. (VIJOS) VOJ 1067 Warcraft III 守望者的烦恼 矩阵快速幂

    https://vijos.org/p/1067   就..挺普通的一道题..自己学一下怎么推式子就可以...细节不多但是我还是日常爆细节..比如说循环写成从负数开始...   只求ac不求美观的丑陋 ...

  7. vijos Warcraft III 守望者的烦恼

    题解 转移方程好写吧 一个一维递推式 然后我们可以构造矩阵优化 嗯,最近学一下递推优化 代码 #include<cstdio> #include<cstring> #inclu ...

  8. [vijos1067]Warcraft III 守望者的烦恼

    就是上次考得fyfy.竟然是原题... // It is made by XZZ #include<cstdio> #include<algorithm> #include&l ...

  9. vijosP1067Warcraft III 守望者的烦恼

    vijosP1067Warcraft III 守望者的烦恼 链接:https://vijos.org/p/1067 [思路] 矩阵乘法. 可以得出递推式:      f[i]=sum{ f[n-1], ...

随机推荐

  1. View的相关原理(读书笔记)

    View的使用方法相关: 1.setContentView() 2.LayoutInflater.inflate() PS:本质上setContentView()方法最终也是通过LayoutInfla ...

  2. urllib、urllib2、urllib3区别和使用

    python3中把urllib和urllib合并为一个库了,urllib对应urllib.request 1.) python 中最早内置拥有的网络请求模块就是 urllib,我们可以看一下 urll ...

  3. [FE] 有效开展一个前端项目2 (vuejs-templates/webpack)

      1.安装 nodejs.npm $ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - $ sudo apt-get i ...

  4. HTTP请求方式

    HTTP协议中请求的8中方法 OPTIONS获取服务器支持的HTTP请求方法: HEAD跟get很像,但是不返回响应体信息,用于检查对象是否存在,并获取包含在响应消息头中的信息. GET向特定的资源发 ...

  5. H5(ionic2+VScode) 环境安装

    一:node.js.npm.cnpm.cordova环境安装 介绍下概念 node.js 非阻塞异步的Ajax 操作基础框架. npm 国外的node.js 包管理器 cnpm 国内淘宝的node.j ...

  6. Ubuntu 增加swap空间大小

    1. create a 1G file for the swap. sudo fallocate -l 1G /swapfile we can verify that the correct amou ...

  7. formValidator 插件 使用总结

    1. 大小写的问题, formvalidator 的属性 大小写问题一定要注意, 在踩过的坑里就包括这个, 把所有属性的第二个字母的开头全部写成大写 ,导致提示信息不能用,这个问题纠结了好久 2.er ...

  8. Find out where to contain the smartforms

    Go to table E071 and give smarforms name and it will give the transport req for that. Run SE03, choo ...

  9. Day2数据结构和算法

    2019-02-28,10:23:52 算法效率的度量方法 事后统计方法:为每一个程序编制测试程序 ,比较时间.(很麻烦,没有普遍适用性) 事前分析估算方法:在计算机程序编写前,依据统计方法对算法进行 ...

  10. jquery点击回到顶部

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...