• 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 }
  • 相关阅读:
    Html-Css 从入门到放弃(一)基础知识
    PHP7 学习笔记(十)会话控制
    Redis模块学习笔记(一)RediSearch简单使用
    PHP7 学习笔记(九)phpsize动态编译openssl扩展 (微信公众平台)
    Git与GitHub学习笔记(五)一次提交失败的记录
    PHP7 学习笔记(八)JetBrains PhpStorm 2017.1 x64 MySQL数据库管理工具的使用
    PHP7 学习笔记(七)如何使用zephir编译一个扩展记录
    阿里云(四)Linux 实例常用内核网络参数介绍与常见问题处理
    阿里云(三)安全组
    流媒体技术学习笔记之(十七)FFmpeg 3.3《希尔伯特》-新版本的亮点
  • 原文地址:https://www.cnblogs.com/ywjblog/p/9706571.html
Copyright © 2020-2023  润新知