• [矩阵十题第七题]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,否则可能会溢出

    来源

    杜杜我爱你个人原创


      最朴实的dp方程

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

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

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

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

      因此我们有

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

    Code

      1 /**
      2  * vijos
      3  * Problem#1067
      4  * Accepted
      5  * Time:46ms
      6  * Memory:1016k
      7  */
      8 #include<iostream>
      9 #include<cstdio>
     10 #include<cctype>
     11 #include<cstring>
     12 #include<cstdlib>
     13 #include<fstream>
     14 #include<sstream>
     15 #include<algorithm>
     16 #include<map>
     17 #include<set>
     18 #include<queue>
     19 #include<vector>
     20 #include<stack>
     21 using namespace std;
     22 typedef bool boolean;
     23 #define INF 0xfffffff
     24 #define smin(a, b) a = min(a, b)
     25 #define smax(a, b) a = max(a, b)
     26 template<typename T>
     27 inline void readInteger(T& u){
     28     char x;
     29     int aFlag = 1;
     30     while(!isdigit((x = getchar())) && x != '-');
     31     if(x == '-'){
     32         x = getchar();
     33         aFlag = -1;
     34     }
     35     for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0');
     36     ungetc(x, stdin);
     37     u *= aFlag;
     38 }
     39 
     40 #define moder 7777777
     41 
     42 typedef class Matrix {
     43     public:
     44         int* p;
     45         int lines, cols;
     46         Matrix():p(NULL), lines(0), cols(0)    {    } 
     47         Matrix(int lines, int cols):lines(lines), cols(cols) {
     48             p = new int[(lines * cols)];
     49         }
     50         
     51         int* operator [](int pos) {
     52             return p + pos * cols;
     53         } 
     54 
     55         Matrix operator *(Matrix b) {
     56             if(cols != b.lines)    return Matrix();
     57             Matrix res = Matrix(lines, b.cols);
     58             for(int i = 0; i < lines; i++) {
     59                 for(int j = 0; j < b.cols; j++) {
     60                     res[i][j] = 0;
     61                     for(int k = 0; k < cols; k++) {
     62                         (res[i][j] += ((*this)[i][k] * 1LL * b[k][j]) % moder) %= moder;
     63                     }
     64                 }
     65             }
     66             return res;
     67         }
     68 }Matrix;
     69 
     70 template<typename T>
     71 T pow(T a, int pos) {
     72     if(pos == 1)    return a;
     73     T temp = pow(a, pos / 2);
     74     if(pos & 1)    return temp * temp * a;
     75     return temp * temp;
     76 }
     77 
     78 int k, n;
     79 Matrix unit;
     80 Matrix org;
     81 
     82 inline void init() {
     83     readInteger(k);
     84     readInteger(n);    
     85 }
     86 
     87 inline void solve() {
     88     org = Matrix(k, 1);
     89     org[k - 1][0] = 1;
     90     for(int i = k - 2; i >= 0; i--) {
     91         org[0][i] = 0;
     92         for(int j = i; j < k; j++)
     93             org[0][i] += org[0][j];
     94     }
     95     if(n < k) {
     96         printf("%d", org[0][n]);
     97         return;
     98     }
     99     unit = Matrix(k, k);
    100     for(int i = 0; i < k; i++)
    101         unit[0][i] = 1;
    102     for(int i = 1; i < k; i++)
    103         for(int j = 0; j < k; j++)
    104             unit[i][j] = (i == j + 1) ? (1) : (0);
    105     Matrix res = pow(unit, n - k + 1) * org;
    106     printf("%d", res[0][0]);
    107 }
    108 
    109 int main() {
    110     init();
    111     solve(); 
    112     return 0;
    113 }
  • 相关阅读:
    Vector用法。
    error LNK2001的解决方法
    指针(详解)
    xxx cannot be resolved to a type
    springmvc写了方法无法访问
    java lombok包在maven已经配置,但是注解没用
    系统提供的相关intent
    Activity小结
    BrocastReceiver入门
    AppWidget入门
  • 原文地址:https://www.cnblogs.com/yyf0309/p/6568320.html
Copyright © 2020-2023  润新知