C++矩阵加速经典题目:Warcraft III 守望者的烦恼 [vijos 1067]
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]的更多相关文章
- [矩阵十题第七题]vijos 1067 Warcraft III 守望者的烦恼 -矩阵快速幂
背景 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她传送到后面的监狱内查看,她比较懒,一般不查看 ...
- 矩阵经典题目七:Warcraft III 守望者的烦恼(矩阵加速递推)
https://www.vijos.org/p/1067 非常easy推出递推式f[n] = f[n-1]+f[n-2]+......+f[n-k]. 构造矩阵的方法:构造一个k*k的矩阵.当中右上角 ...
- vijos 1067 Warcraft III 守望者的烦恼 矩阵
题目链接 我们可以很容易的推出dp的式子, dp[i] = sigma(j : 1 to k) dp[i-j]. 但是n太大了, 没有办法直接算, 所以我们构造一个矩阵, 然后快速幂就好了. 就像这样 ...
- 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 ...
- [Vijos1067]Warcraft III 守望者的烦恼(DP + 矩阵优化)
传送门 可知 f[i] = f[i - 1] + f[i - 2] + ... + f[i - k] 直接矩阵优化就好了 #include <cstdio> #include <cs ...
- (VIJOS) VOJ 1067 Warcraft III 守望者的烦恼 矩阵快速幂
https://vijos.org/p/1067 就..挺普通的一道题..自己学一下怎么推式子就可以...细节不多但是我还是日常爆细节..比如说循环写成从负数开始... 只求ac不求美观的丑陋 ...
- vijos Warcraft III 守望者的烦恼
题解 转移方程好写吧 一个一维递推式 然后我们可以构造矩阵优化 嗯,最近学一下递推优化 代码 #include<cstdio> #include<cstring> #inclu ...
- [vijos1067]Warcraft III 守望者的烦恼
就是上次考得fyfy.竟然是原题... // It is made by XZZ #include<cstdio> #include<algorithm> #include&l ...
- vijosP1067Warcraft III 守望者的烦恼
vijosP1067Warcraft III 守望者的烦恼 链接:https://vijos.org/p/1067 [思路] 矩阵乘法. 可以得出递推式: f[i]=sum{ f[n-1], ...
随机推荐
- 开启mysql-binlog日志操作步骤
步骤1:找到mysql主库的配置文件(注意:不能为从库),lunix系统路径一般为/etc/my.cnf 步骤2:修改配置文件(可以提前备份一下)以开启mysql-binlog功能.添加以下3行: l ...
- tensorflow models api:ValueError: Tensor conversion requested dtype string for Tensor with dtype float32: 'Tensor("arg0:0", shape=(), dtype=float32, device=/device:CPU:0)'
tensorflow models api:ValueError: Tensor conversion requested dtype string for Tensor with dtype flo ...
- 遇到的[]bug
"Runtime Error Message:reference binding to null pointer of type 'struct value_type' Last execu ...
- 一条分页的SQL语句
1.概述 在网页中如果显示的数据太多就会占据过多的页面,而且显示速度也会很慢.为了控制每次在页面上显示数据的数量,就可以利用分页来显示数据. 2.技术要点 在SQL Server中要实现SQL分页,需 ...
- layui xtree 实现一级节点单选 ,子节点复选
在外部定义变量和方法 //定义变量 接收顶级节点的值 var topValue; // 获取顶级节点值的方法 function getParent(value) { var val = project ...
- k8s之调度约束
k8s调度约束有两种:第一种,直接指定某台node主机:这种形势将直接跳过调度器.如下: 第二种:先给各node指定标签,然后在通过标签的形势来关联node,这种形势人就会调用到调度器.如下: yao ...
- 阿里巴巴 Weex
原文链接:https://blog.csdn.net/zz901214/article/details/79168707/ 分享嘉宾:侑夕 阿里巴巴高级前端工程师(上张帅哥的图镇楼,看完,更有动力学习 ...
- 985. Sum of Even Numbers After Queries
We have an array A of integers, and an array queries of queries. For the i-th query val = queries[i] ...
- CodeWarrior 10 配置Jlint初始化文件
新建一个项目之后,飞思卡尔的仿真器的配置不如德州仪器那么简单.他需要一些配置. 当我们新建一个工程后,可以采取如下步骤配置Jlint: 1.右击工程名,选择属性. 2.在Run/Debug Setti ...
- windows内核驱动内存管理之Lookaside使用
Windows内存管理中使用了类似于容器的东西,叫做Lookaside对象,每次程序员申请内存都会从Lookaside里面申请,只有不足的时候,Lookaside才会向内存又一次申请内存空间,这样减少 ...