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

时间:2022-09-19 01:35:32

背景

守望者-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,否则可能会溢出

来源

杜杜我爱你个人原创


  最朴实的dp方程

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

  根据加法原理,把所有可以到达n号*的出发点(n-i)的值累加起来。

  再看数据范围,O(nk)果断超时,不解释(除非用超算评测或许还可以AC)

  总觉得和线性递推长得差不多,于是考虑用矩阵快速幂来优化。首先表示出最初的状态

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

  其中f[0] = 1。接着按照套路来进行矩阵乘法得到下一项

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

  因此我们有

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

  又因为矩阵乘法满足结合律,所以就对那么看起来由0和1构成的矩阵进行快速幂就好了。

Code

 /**
* vijos
* Problem#1067
* Accepted
* Time:46ms
* Memory:1016k
*/
#include<iostream>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
#include<fstream>
#include<sstream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
typedef bool boolean;
#define INF 0xfffffff
#define smin(a, b) a = min(a, b)
#define smax(a, b) a = max(a, b)
template<typename T>
inline void readInteger(T& u){
char x;
int aFlag = ;
while(!isdigit((x = getchar())) && x != '-');
if(x == '-'){
x = getchar();
aFlag = -;
}
for(u = x - ''; isdigit((x = getchar())); u = (u << ) + (u << ) + x - '');
ungetc(x, stdin);
u *= aFlag;
} #define moder 7777777 typedef class Matrix {
public:
int* p;
int lines, cols;
Matrix():p(NULL), lines(), cols() { }
Matrix(int lines, int cols):lines(lines), cols(cols) {
p = new int[(lines * cols)];
} int* operator [](int pos) {
return p + pos * cols;
} Matrix operator *(Matrix b) {
if(cols != b.lines) return Matrix();
Matrix res = Matrix(lines, b.cols);
for(int i = ; i < lines; i++) {
for(int j = ; j < b.cols; j++) {
res[i][j] = ;
for(int k = ; k < cols; k++) {
(res[i][j] += ((*this)[i][k] * 1LL * b[k][j]) % moder) %= moder;
}
}
}
return res;
}
}Matrix; template<typename T>
T pow(T a, int pos) {
if(pos == ) return a;
T temp = pow(a, pos / );
if(pos & ) return temp * temp * a;
return temp * temp;
} int k, n;
Matrix unit;
Matrix org; inline void init() {
readInteger(k);
readInteger(n);
} inline void solve() {
org = Matrix(k, );
org[k - ][] = ;
for(int i = k - ; i >= ; i--) {
org[][i] = ;
for(int j = i; j < k; j++)
org[][i] += org[][j];
}
if(n < k) {
printf("%d", org[][n]);
return;
}
unit = Matrix(k, k);
for(int i = ; i < k; i++)
unit[][i] = ;
for(int i = ; i < k; i++)
for(int j = ; j < k; j++)
unit[i][j] = (i == j + ) ? () : ();
Matrix res = pow(unit, n - k + ) * org;
printf("%d", res[][]);
} int main() {
init();
solve();
return ;
}