zoukankan      html  css  js  c++  java
  • 矩阵快速幂

    矩阵乘法:

       a(n, m), b(m, p) 为两个二维矩阵 相乘可得矩阵c(n, p)  a中每一行和b中每一列相对应数的乘积之和;

    1、

      hdoj 1575--Tr A   http://acm.hdu.edu.cn/showproblem.php?pid=1575  

      A为一个矩阵 求A^K中主对角线之和 , 结果取模;

    #define mod 9973
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    struct matrix
    {
        int a[15][15];
    }; int n;
    matrix mul(matrix a, matrix b)
    {
        matrix ret;
        memset(ret.a, 0, sizeof(ret.a));
        for(int i = 0; i < n; i++)
        {
            for(int k = 0; k < n; k++)
                if(a.a[i][k])
                    for(int j = 0; j < n; j++)
                        if(b.a[k][j])
                            ret.a[i][j]=(a.a[i][k]*b.a[k][j]+ret.a[i][j])%mod;
        }
        return ret;
    }
    matrix mpower(matrix tem, int m)
    {
        matrix I;
        for(int i = 0; i < 15; i++)
            for(int j = 0; j < 15; j++)
                I.a[i][j] = (i==j);
        while(m)
        {
            if(m&1)
                I = mul(I, tem);
                m >>= 1;
            tem = mul(tem, tem);
        }
        return I;
     }
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            int m;
            matrix num;
            scanf("%d%d", &n, &m);
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++)
                    scanf("%d", &num.a[i][j]);
            num = mpower(num, m);
            int sum = 0;
            for(int i = 0; i < n; i++)
            {
                sum = (sum+num.a[i][i])%mod;
            }
            printf("%d
    ", sum);
        }
        return 0;
    }

    2、

      Poj 3070--Fibonacci      http://poj.org/problem?id=3070

        奇妙, 二维矩阵a{0, 1, 1, 1}^n = F(n) && (n != 0); Fib数列矩阵求法 ; {a,  b} * {0, 1, 1, 1}  = {b, a+b};  

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    const int MOD = 1e4;
    struct matrix
    {
        int a[2][2];
    };
    matrix Matrixmul(matrix a, matrix b)
    {
       // int cnt = 0;
        matrix ret;
        memset(ret.a, 0, sizeof(ret.a));
        for(int i = 0; i < 2; i++)
            for(int k = 0; k < 2; k++)
            {
                    if(a.a[i][k])
                    for(int j = 0; j < 2; j++)
                    {
                        if(b.a[k][j])
                            ret.a[i][j]=(a.a[i][k]*b.a[k][j]+ret.a[i][j])%MOD;
                    }
                 /*   cnt++;
                    for(int L = 0; L < 2; L++){
                        for(int M = 0; M < 2; M++)
                            printf("%d ", ret.a[L][M]);
                        printf("
    ");
                    }
    
                    printf("%d
    
    
    ", cnt);*/
            }
            return ret;
    }
    matrix Matrixpow(matrix a, int n)
    {
        matrix I;
        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 2; j++)
                I.a[i][j] = (i==j);
        while(n)
        {
            if(n&1)
                I = Matrixmul(I, a);
            n >>= 1;
            a = Matrixmul(a, a);
        }
        return I;
    }
    int main()
    {
        int n;
        while(scanf("%d", &n)!= EOF, n != -1)
        {
            if(n == 0)
                printf("0
    ");
            else
            {
                matrix num, tem;
                num.a[0][0] = 0;
                num.a[0][1] = 1;
                num.a[1][0] = 1;
                num.a[1][1] = 1;
                tem = Matrixpow(num, n);
                printf("%d
    ", tem.a[0][1]);
            }
        }
        return 0;
    }

    3、 

      Poj3233--Matrix Power Series (递推+矩阵) re++!!

      S = A + A2 + A3 + … + Ak  ;A为矩阵;

      例子:

        (1)k = 6 有: S(6) = (1 + A^3) * (A + A^2 + A^3) = (1 + A^3) * S(3)。
        (2)k = 7 有: S(7) = A + (A + A^4) * (A + A^2 + A^3) = A + (A + A^4) * S(3)。
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    int n, m, k; int MOD;
    struct mat
    {
        int  a[41][41];
    };
    mat d;
    struct
    {
        mat expo(mat a, int k)
        {
            /*if(k == 1)
                return a;*/
            mat e;
            memset(e.a, 0, sizeof(e.a));
            for(int i = 0; i < n; i++)
                e.a[i][i] = 1;
            if(k == 0)
                return e;
            while(k)
            {
                if(k&1)
                    e=mul(e, a);
                k>>=1;
                a=mul(a, a);
            }
            return e;
        }
        mat mul(mat a, mat b)
        {
            mat ret;
            memset(ret.a, 0, sizeof(ret.a));
            for(int i = 0; i < n; i++)
                for(int k = 0; k < n; k++)
                    if(a.a[i][k])
                        for(int j = 0; j < n; j++)
                            if(b.a[k][j])
                            {
                                ret.a[i][j]=a.a[i][k]*b.a[k][j]+ret.a[i][j];
                                if(ret.a[i][j]>=MOD)
                                    ret.a[i][j]%=MOD;
                            }
            return ret;
        }
    }MmM;//Matrix_muti_Modern;
    void print(mat a)
    {
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < n; j++)
                printf(j==n-1?"%d
    ":"%d ", a.a[i][j]);
        }
    }
    mat add(mat a, mat b)
    {
        mat t;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
            {
                t.a[i][j]=a.a[i][j]+b.a[i][j];
                if(t.a[i][j] >= m)
                    t.a[i][j]%=MOD;
            }
        return t;
    }
    //(1)k = 6 有: S(6) = (1 + A^3) * (A + A^2 + A^3) = (1 + A^3) * S(3)。
    //(2)k = 7 有: S(7) = A + (A + A^4) * (A + A^2 + A^3) = A + (A + A^4) * S(3)。
    mat sum(int k)
    {
        if(k == 1)
            return d;
        if(k&1)
            return add(sum(k-1), MmM.expo(d, k));
        else
        {
            mat s=sum(k>>1);
            return add(s, MmM.mul(s, MmM.expo(d, k>>1))); 
            //S(n>>1)+S(n>>1)*A^(n>>1)=S(n>>1)(1+A^(n>>1)&&S(n>>1)=(A1+...+A(n>>1)); 
        }
    }
    int main()
    {
        mat tem;
        while(scanf("%d%d%d", &n, &k, &m) != EOF)
        {
            MOD = m;
            for(int i = 0; i < n; i++)
                for(int j = 0; j < n; j++)
                {
                    scanf("%d", &d.a[i][j]);
                    if(d.a[i][j] >= MOD)
                        d.a[i][j]%=MOD;
                }
            tem = sum(k);
            print(tem);
        }
        return 0;
    }

    4、

      Poj3735--Training little cats

      n, m, k; Ai(i =1,2, 3)代表操作; n只猫, k条操作, 重复m次;  主要是构造矩阵;

      A1 a (a食物数+1);  A2 a, b(a食物给b); A3 a(吃完所有);

      构造矩阵Mat(0--n, 0--n);  A1时Mat[0][a]+1; A2时交换a, b列; A3时a列置0

      题解:http://www.cppblog.com/y346491470/articles/157284.html 

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define LL long long
    using namespace std;
    struct mat
    {
        LL a[101][101];
    };
    int n, m, k;
    mat matinit(mat a)
    {
        memset(a.a, 0, sizeof(a.a));
        for(int i = 0; i <= n; i++)
            a.a[i][i] = 1;
        return a;
    }
    mat matmul(mat a, mat b)
    {
        mat res;
        memset(res.a, 0, sizeof(res.a));
        for(int i = 0; i <= n; i++)
            for(int k = 0; k <= n; k++)
                if(a.a[i][k])
                    for(int j = 0; j <= n; j++)
                        if(b.a[k][j])
                            res.a[i][j] += a.a[i][k]*b.a[k][j];
        return res;
    }
    mat matpow(mat a, int k)
    {
        mat I;
        memset(I.a, 0, sizeof(I.a));
        for(int i = 0; i <= n; i++)
            I.a[i][i] = 1;
       /* if(k == 0)
            return I; */
        while(k)
        {
            if(k&1)
                I=matmul(I, a);
            k>>=1;
            a=matmul(a, a);
        }
        return I;
    }
    int main()
    {
        while(scanf("%d%d%d", &n, &m, &k) != EOF ,n ,m, k)
        {
            mat ret, num;
            char str[2];  int a, b;
            num = matinit(num);
            /*for(int i = 0; i <= n; i++)
                for(int j = 0; j <= n; j++)
                    printf("%d
    ", num.a[i][j]);*/
            for(int i = 0; i < k; i++)
            {
                cin >> str;
                if(str[0] == 'g')
                {
                    scanf("%d", &a);
                    num.a[0][a] +=1;
                }
                if(str[0] == 'e')
                {
                    scanf("%d", &a);
                    for(int i = 0; i <= n; i++)
                        num.a[i][a] = 0;
                }
                if(str[0] == 's')
                {
                    scanf("%d%d", &a, &b);
                    for(int i = 0; i <= n; i++)
                    {
                        LL temp = num.a[i][a];
                        num.a[i][a] = num.a[i][b];
                        num.a[i][b] = temp;
                    }
                }
            }
            ret = matpow(num, m);
            for(int i = 1; i <= n; i++)
                printf(i==n?"%lld
    ":"%lld ", ret.a[0][i]);
        }
        return 0;
    }

    5、

      Poj 3150 有点神,

  • 相关阅读:
    Construct Binary Tree from Preorder and Inorder Traversal
    Construct Binary Tree from Inorder and Postorder Traversal
    Maximum Depth of Binary Tree
    Sharepoint 2013 创建TimeJob 自动发送邮件
    IE8 不能够在Sharepoint平台上在线打开Office文档解决方案
    TFS安装与管理
    局域网通过IP查看对方计算机名,通过计算机名查看对方IP以及查看在线所有电脑IP
    JS 隐藏Sharepoint中List Item View页面的某一个字段
    SharePoint Calculated Column Formulas & Functions
    JS 两个一组数组转二维数组
  • 原文地址:https://www.cnblogs.com/soTired/p/5109168.html
Copyright © 2011-2022 走看看