zoukankan      html  css  js  c++  java
  • POJ3233 Matrix Power Series 矩阵快速幂 矩阵中的矩阵

    Matrix Power Series
    Time Limit: 3000MS   Memory Limit: 131072K
    Total Submissions: 27277   Accepted: 11143

    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
     
    题意: 这题就是求一个矩阵的和式:S(k),直接对和式建立递推:

    A^i是一个矩阵

    很显然,把每个A^i算出来是不行的,所以我们得找找关系

    因为这里牵扯到了矩阵相加求和,所以我们可以想到构建一个包含A的矩阵(只要包含A和两个一就行,这样是为了最后能得到A^1+A^2+...+A^K的式子)

    其中1是单位矩阵,单位矩阵是左对角线为1的矩阵

    然后容易得到:

    可以看出这个分块矩阵的左下角那块就可以得到要求的解S

    我们取这一块,再减去一个单位矩阵1即可。

    参考博客:https://www.cnblogs.com/pdev/p/4063669.html

    #include <map>
    #include <set>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define debug(a) cout << #a << " " << a << endl
    using namespace std;
    const int maxn = 110;
    const int mod = 2;
    typedef long long ll;
    struct matrix {
        ll a[maxn][maxn];
    };
    matrix base, ans;
    ll n, t, m;
    matrix multip( matrix x, matrix y ) {
        matrix tmp;
        for( ll i = 0; i < 2*n; i ++ ) {
            for( ll j = 0; j < 2*n; j ++ ) {
                tmp.a[i][j] = 0;
                for( ll k = 0; k < 2*n; k ++ ) {
                    tmp.a[i][j] = ( tmp.a[i][j] + x.a[i][k] * y.a[k][j] ) % m;
                }
            }
        }
        return tmp;
    }
    void f( ll x ) {
        while( x ) {
            if( x&1 ) {
                ans = multip( ans, base );
            }
            base = multip( base, base );
            x /= 2;
        }
    }
    int main() {
        while( cin >> n >> t >> m ) {
            memset( ans.a, 0, sizeof(ans.a) );
            memset( base.a, 0, sizeof(base.a) );
            for( ll i = 0; i < n; i ++ ) {
                for( ll j = 0; j < n; j ++ ) {
                    cin >> base.a[i][j];
                }
            }
            for( ll i = n; i < 2*n; i ++ ) { //两个单位矩阵
                base.a[i][i-n] = base.a[i][i] = 1;
            }
           //上面两个for循环是为了构建出新的包含A的矩阵
            for( ll i = 0; i < 2*n; i ++ ) {
                ans.a[i][i] = 1;
            }
            f(t+1);  //由上面举的例子可以看出要求出n次方,得算n+1次
            for( ll i = n; i < 2*n; i ++ ) {
                for( ll j = 0; j < n; j ++ ) {
                    if( i == j+n ) {
                        ans.a[i][j] --;
                    }
                    if( j != n-1 ) {
                        cout << ( ans.a[i][j] + m ) % m << " ";
                    } else {
                        cout << ( ans.a[i][j] + m ) % m << endl;
                    }
                }
            }
        }
        return 0;
    }
        
    

      

    彼时当年少,莫负好时光。
  • 相关阅读:
    AD域渗透总结
    CTF
    ew做代理 进一步内网渗透
    CVE-2019-0708复现
    win 内网frp反弹到内网liunx
    Liunx反弹shell的几种方式
    sql到python正则
    PHP面向对象学习-属性 类常量 类的自动加载 构造函数和析构函数 访问控制(可见性)
    PHP反序列化学习
    PHP面向对象学习
  • 原文地址:https://www.cnblogs.com/l609929321/p/9318746.html
Copyright © 2011-2022 走看看