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. Appium基础知识与环境搭建

    基础知识:  环境搭建: 1.安装jdk,配置java环境变量 (1)新建变量"JAVA_HOME",变量值"D:\Frameworks\Java\jdk1.8.0_18 ...

  2. linux io的cfq代码理解

    内核版本: 3.10内核. CFQ,即Completely Fair Queueing绝对公平调度器,原理是基于时间片的角度去保证公平,其实如果一台设备既有单队列,又有多队列,既有快速的NVME,又有 ...

  3. JS中this的四种用法

    1.在一般函数方法中使用 this 指代全局对象 2.作为对象方法调用,this 指代上级对象 3.作为构造函数调用,this 指代new 出的对象 4.apply 调用 ,apply方法作用是改变函 ...

  4. 在java程序当中怎么获取一个文件的路径

    在java程序当中怎么获取一个文件的路径? * 当这个文件在类路径下的时候(在src/bin目录下的时候): String absolutePath = Thread.currentThread(). ...

  5. 20175213《Java程序设计》实验二Java面向对象程序设计实验报告

    实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装,继承,多态 3.初步掌握UML建模 4.熟悉S.O.L.I.D原则 5.了解设计模式 知识总结 1.伪代码 2.产品代码: ...

  6. fiddler抓取https请求

    Fiddler抓取https设置详解(图文):https://www.cnblogs.com/joshua317/p/8670923.html Fiddler要抓取到https请求我们还需要Fiddl ...

  7. Swagger2 header 添加token

    @Bean public Docket apiDocument() { return new Docket(DocumentationType.SWAGGER_2) .groupName(" ...

  8. windows下git 同步数据到github的常见问题

    常用排错方法: 1,查看连接是否正常. 2,push数据有时会报错,这是由于远程repository和我本地的repository冲突造成. 解决方法: 1.使用强制push的方法: git push ...

  9. 基于SDL2实现俄罗斯方块

    俄罗斯方块有多种旋转规则,我这里采用的是SRS.如果要改变旋转规则的话也很方便. SRS: 内容后续补充.. 代码:https://github.com/CknightX/sdl_Tetris 素材来 ...

  10. Oracle导入建表的sql文件类型