zoukankan      html  css  js  c++  java
  • POJ3233:Matrix Power Series(矩阵快速幂+二分)

    http://poj.org/problem?id=3233

    题目大意:给定矩阵A,求A + A^2 + A^3 + … + A^k的结果(两个矩阵相加就是对应位置分别相加)。输出的数据mod m。k<=10^9。
    这道题两次二分,相当经典。首先我们知道,A^i可以二分求出。然后我们需要对整个题目的数据规模k进行二分。比如,当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,即可得到原问题的答案。

    代码如下:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <math.h>
    #include <queue>
    using namespace std;
    
    struct matrix
    {
        int a[31][31];
    } init,res;
    int n,k,mod;
    matrix Mult(matrix x,matrix y)
    {
        matrix tmp;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                tmp.a[i][j]=0;
                for(int k=0; k<n; k++)
                    tmp.a[i][j]=(tmp.a[i][j]+x.a[i][k]*y.a[k][j])%mod;
            }
        }
        return tmp;
    }
    matrix Pow(matrix x,int k)
    {
        matrix tmp;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
                tmp.a[i][j]=(i==j);
        }
        while(k)
        {
            if(k&1)
                tmp=Mult(tmp,x);
            k>>=1;
            x=Mult(x,x);
        }
        return tmp;
    }
    matrix Add(matrix x,matrix y)
    {
        matrix tmp;
        for(int i=0; i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                tmp.a[i][j]=(x.a[i][j]+y.a[i][j])%mod;
            }
        }
        return tmp;
    }
    matrix Sum(matrix x,int k)
    {
        if(k==1)
            return x;
        matrix tmp=Sum(x,k/2),y;
        if(k&1)
        {
            y=Pow(x,k/2+1);
            tmp=Add(Mult(y,tmp),tmp);
            return Add(tmp,y);
        }
        else
        {
            y=Pow(x,k/2);
            return Add(Mult(y,tmp),tmp);
        }
    }
    int main()
    {
        while(scanf("%d%d%d",&n,&k,&mod)!=EOF)
        {
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<n; j++)
                {
                    scanf("%d",&init.a[i][j]);
                    init.a[i][j]%=mod;
                }
            }
            res=Sum(init,k);
            for(int i=0; i<n; i++)
            {
                for(int j=0; j<n; j++)
                {
                    if(j==0) printf("%d",res.a[i][j]);
                    else printf(" %d",res.a[i][j]);
                }
                printf("
    ");
            }
        }
        return 0;
    }

     其他大神的想法:

    题目分析:矩阵快速幂。首先我们知道 A^x 可以用矩阵快速幂求出来。其次可以对k进行二分,每次将规模减半,分k为奇偶两种情况,如当k = 6和k = 7时有:

          k = 6 有: S(6) = (1 + A^3) * (A + A^2 + A^3) = (1 + A^3) * S(3)。
          k = 7 有: S(7) = A + (A + A^4) * (A + A^2 + A^3) = A + (A + A^4) * S(3)。
     
    ps:对矩阵定义成结构体Matrix,求S时用递归,程序会比较直观,好写一点。当然定义成数组,然后再进行一些预处理,效率会更高些。
     
  • 相关阅读:
    linux自动挂载
    VUE 封装 api类
    数据库中如何判断某参数为空就不执行where条件
    axios 拦截 , 页面跳转, token 验证(非本人原创)
    springboot 集成 WebSocket (非本人原创)
    spring cloud整合 websocket 的那些事
    前后端消息推送
    spring cloud 之eureka配置
    spring cloud 之demo
    linux 进程的 5 大段
  • 原文地址:https://www.cnblogs.com/zhangmingcheng/p/4124868.html
Copyright © 2011-2022 走看看