zoukankan      html  css  js  c++  java
  • POJ 3233 Matrix Power Series 【经典矩阵快速幂+二分】

    任意门:http://poj.org/problem?id=3233

    Matrix Power Series
    Time Limit: 3000MS   Memory Limit: 131072K
    Total Submissions: 28619   Accepted: 11646

    Description

    Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak.

    Input

    The input contains exactly one test case. The first line of input contains three positive integers n (n ≤ 30), k (k ≤ 109) and m (m < 104). Then follow n lines each containing n nonnegative integers below 32,768, giving A’s elements in row-major order.

    Output

    Output the elements of S modulo m in the same way as A is given.

    Sample Input

    2 2 4
    0 1
    1 1

    Sample Output

    1 2
    2 3

    Source

    POJ Monthly--2007.06.03, Huang, Jinsong

    题意概括:

    给一个 N 维方阵 A ,求 A+A^2+A^3+ ... +A^k ,结果模 m;

    解题思路:

    矩阵快速幂解决矩阵幂运算(本质是二分优化);

    求前缀和二分:

    比如,当k=6时,有:
        A + A^2 + A^3 + A^4 + A^5 + A^6 =(A + A^2 + A^3) + A^3*(A + A^2 + A^3)
        应用这个式子后,规模k减小了一半。我们二分求出A^3后再递归地计算A + A^2 + A^3,即可得到原问题的答案。

    AC code:

     1 #include <cstdio>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <cstring>
     5 #include <cmath>
     6 #define LL long long
     7 using namespace std;
     8 const int MAXN = 55;
     9 int N, Mod;
    10 
    11 struct mat
    12 {
    13     int m[MAXN][MAXN];
    14 }base;
    15 
    16 mat mult(mat a, mat b)
    17 {
    18     mat res;
    19     memset(res.m, 0, sizeof(res));
    20     for(int i = 0; i < N; i++)
    21     for(int j = 0; j < N; j++){
    22         if(a.m[i][j])
    23             for(int k = 0; k < N; k++)
    24                 res.m[i][k] = (res.m[i][k] + a.m[i][j] * b.m[j][k])%Mod;
    25     }
    26     return res;
    27 }
    28 
    29 mat add(mat a, mat b)
    30 {
    31     mat res;
    32     for(int i = 0; i < N; i++)
    33     for(int j = 0; j < N; j++)
    34         res.m[i][j] = (a.m[i][j] + b.m[i][j])%Mod;
    35     return res;
    36 }
    37 
    38 mat qpow(mat a, int k)
    39 {
    40     mat ans;
    41     memset(ans.m, 0, sizeof(ans.m));
    42     for(int i = 0; i < N; i++) ans.m[i][i] = 1;
    43 
    44     while(k){
    45         if(k&1) ans = mult(ans, a);
    46         k>>=1;
    47         a=mult(a, a);
    48     }
    49     return ans;
    50 }
    51 
    52 mat solve(int K)
    53 {
    54     if(K == 1) return base;
    55     mat res;
    56     memset(res.m, 0, sizeof(res.m));
    57     for(int i = 0; i < N; i++) res.m[i][i] = 1;
    58 
    59     res = add(res, qpow(base, K>>1));
    60     res = mult(res, solve(K>>1));
    61     if(K&1) res = add(res, qpow(base, K));
    62 
    63     return res;
    64 }
    65 
    66 int main()
    67 {
    68     int K;
    69     mat ans;
    70     scanf("%d %d %d", &N, &K, &Mod);
    71     for(int i = 0; i < N; i++)
    72     for(int j = 0; j < N; j++){
    73         scanf("%d", &base.m[i][j]);
    74     }
    75     ans = solve(K);
    76     for(int i = 0; i < N; i++){
    77     for(int j = 0; j < N-1; j++)
    78             printf("%d ", ans.m[i][j]);
    79         printf("%d
    ", ans.m[i][N-1]);
    80     }
    81     return 0;
    82 }
    View Code
  • 相关阅读:
    代理模式和装饰模式的理解
    Mysql常用命令
    java动态代理(JDK和cglib)
    MyEclipse中SVN使用步骤
    ActionContext和ServletActionContext小结
    java和unicode
    Win7下telnet使用
    MyEclipse8.5安装SVN插件
    linux常用命令(基础)
    选择TreeView控件的树状数据节点的JS方法
  • 原文地址:https://www.cnblogs.com/ymzjj/p/9919832.html
Copyright © 2011-2022 走看看