• POJ3233 Matrix Power Series


    一道英文题,自然要有优秀的故事背景和完美的题面以及简明的题意
    尤达大师决定交给你和绝地大师欧比旺一项重要的任务:计算密码(尤达大师只有3个手指头,从种族发展角度,不善数学)
    已知有一个n*n的矩阵和一个正整数k,根据安纳金大师的推算,密码为一个矩阵S
    S = A + A^2 + A^3 + ... + A^k,最后对m取模
    欧比旺大师在飞快的推算中,你看着他计算,露出了坏笑,打开了电脑敲起了整个共和国只有你会的上古语言c++...

    给定n*n的矩阵和一个整数K,求S = A + A^2 + A^3 +... + A^k 对m取模的结果

    显然我们可以想到一个非常暴力的解法

    乘加乘加乘加......

    但是很不幸,这样会Boom

    这题甚至无法生成O(kn^3)的复杂度

    但是我们可以注意到的是,参照等比数列,这一式子矩阵显然是等比矩阵求和,那么我们是否可以利用等比数列的某些性质或是运算加以外推得到计算的方式呢?

    答案是显然的。

    在等比数列求和中,设有:

    S = A + A^2 + A^3 + ... + A^k

    1. k % 2 == 0

      S = (A + A^2 + A^3 + ... + A^k/2) + A^k/2(A + A^2 + A^3 + ... + A^k)

    2. k % 2 == 1

      S = (1 + A^(k/2(下取整)+1)) * (A + A^2 + ... + A^((k-1) / 2)) + A^k/2(下取整)

    这样我们把这种计算方式推广到矩阵,显然我们发现这样每次可以通过二分将范围减小一半

    这样我们就能够利用这种思想,递归求解矩阵

    不是特别好看的代码

     1 #include<iostream>
     2 #include<iomanip>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<stack>
     6 #include<cmath>
     7 #include<map>
     8 #include<set>
     9 #include<ctime>
    10 #include<queue>
    11 #include<vector>
    12 #include<cstdlib>
    13 #include<algorithm>
    14 #define ll long long
    15 #define uint unsigned int
    16 #define ull unsigned long long
    17 using namespace std;
    18 struct shiki {
    19     int num[35][35];
    20 }f[35], ans;
    21 int n, mod, k_on_head;
    22 
    23 inline shiki operator + (const shiki &x, const shiki &y) {
    24     shiki res;
    25     memset(res.num, 0, sizeof(res.num));
    26     for(int i = 1; i <= n; ++i)
    27         for(int j = 1; j <= n; ++j)
    28             res.num[i][j] = (x.num[i][j] + y.num[i][j]) % mod;
    29     return res;
    30 }
    31 
    32 inline shiki operator * (const shiki &x, const shiki &y) {
    33     shiki res;
    34     memset(res.num, 0, sizeof(res.num));
    35     for(int i = 1; i <= n; ++i)
    36         for(int j = 1; j <= n; ++j)
    37             for(int k = 1; k <= n; ++k)
    38                 res.num[i][j] = (res.num[i][j] + x.num[i][k] * y.num[k][j] % mod) % mod;
    39     return res;
    40 }
    41 
    42 inline shiki power(int b) {
    43     shiki res;
    44     memset(res.num, 0, sizeof(res.num));
    45     for(int i = 1; i <= n; ++i) res.num[i][i] = 1;
    46     int cnt = 0;
    47     for(; b; b >>= 1) {
    48         if(b & 1) res = res * f[cnt];
    49         cnt++;
    50     }
    51     return res;
    52 }
    53 
    54 inline void balalalala(int kkksc03) {
    55     int cnt = 1;
    56     for(int i = 0; cnt <= kkksc03; ++i, cnt <<= 1) 
    57         f[i + 1] = f[i] * f[i];    
    58 }
    59 
    60 shiki solve(int ltt) {
    61     if(ltt == 1) return f[0];
    62     shiki p = solve(ltt >> 1);
    63     p = p + p * power(ltt >> 1);
    64     if(ltt & 1) p = p + power(ltt);
    65     return p;
    66 }
    67 
    68 inline void print(const shiki &ans) {
    69     for(int i = 1; i <= n; ++i) {
    70         for(int j = 1; j <= n; ++j)
    71             printf("%d ", ans.num[i][j]);
    72         printf("
    ");
    73     }
    74 }
    75 
    76 int main() {
    77     scanf("%d%d%d", &n, &k_on_head, &mod);
    78     for(int i = 1; i <= n; ++i)
    79         for(int j = 1; j <= n; ++j)
    80             scanf("%d", &f[0].num[i][j]);
    81     balalalala(k_on_head);//预处理每一项 
    82     print(solve(k_on_head));
    83     return 0;
    84 }
  • 相关阅读:
    synchronized 到底该不该用?
    线上Java程序占用 CPU 过高,请说一下排查方法?
    『JVM』我不想知道我是怎么来滴,我就想知道我是怎么没滴
    Golang 实现 Redis(8): TCC分布式事务
    Golang 实现 Redis(7): 集群与一致性 Hash
    Golang 实现 Redis(6): 实现 pipeline 模式的 redis 客户端
    LSM 树详解
    uni-app subNVue 原生子窗体简单使用案例(app端)
    日计不足涓滴成河-自定义响应结果格式化器
    RTT之软件包
  • 原文地址:https://www.cnblogs.com/ywjblog/p/9706571.html
Copyright © 2020-2023  润新知