• poj 3233 Matrix Power Series 矩阵 快速幂 两次二分


    题目地址: http://poj.org/problem?id=3233

    思想: 1模仿快速模幂法 ; 给矩阵写一个快幂

                 2 但是k太大 直接求和还是会tle  这个很像等比数列求和  但是可以递归用二分求,理论基础如下 :

                    求和二分:A+A^2+A...+A^(2k+1)=   A+A^2+...+A^k+A^(k+1)+A^(k+1)*(A+A^2+...+A^k).

                3  矩阵用结构体存储很好用呀  

                   之前 用int **存好像容易超内存 或者时间效率不高 

                4递归函数设计时,把调用递归的放在前面,这样实现自动回溯,而且不会爆栈

                5 用g++提交会runtime error  c++ ac  ,坑爹  搞了一晚上 

    #include<iostream>
    #include<cstdlib>
    #define maxn 101
    using namespace std;
    
    int n;
    int M;
    
    typedef
    struct
    {
       int  m[maxn][maxn];
    
    }matrix;
    
    
    matrix per;
    matrix a;
    void init()
    {
       for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
         {
    
            cin>>a.m[i][j];
            a.m[i][j]%=M;
    
            per.m[i][j]=(i==j);
         }
    }
    matrix multi(matrix a,matrix b)
    {
       matrix ans;
    
       for(int i=0;i<n;i++)
         for(int j=0;j<n;j++)
            {
                 ans.m[i][j]=0;
                for(int k=0;k<n;k++)
                   ans.m[i][j]+=(a.m[i][k]*b.m[k][j])%M;
                     ans.m[i][j]%=M;
    
            }
    
      return ans;
    }
    
    matrix quick_mod(int b)
    {
       matrix ans=per;
       matrix aa=a;
       while(b)
       {
         if(b&1)
         {
            ans=multi(ans,aa);
            b--;
         }
         b>>=1;
         aa=multi(aa,aa);
       }
    
       return ans;
    }
    
    matrix add(matrix a,matrix b)
    {
    
      matrix ans;
      for(int i=0;i<n;i++)
         for(int j=0;j<n;j++)
          {
            ans.m[i][j]=(a.m[i][j]+b.m[i][j])%M;
    
    //        ans.m[i][j]=a.m[i][j]+b.m[i][j];
    //        ans.m[i][j]%=M;
          }
       return ans;
    }
    
    matrix sum(int n)
    {
       if(n==1)  return a;
        matrix temp,b;
        temp = sum(n/2);
        if(n&1)
       {
         matrix b=quick_mod(n/2+1);
         matrix ans=multi(temp,b);
         ans=add(ans,temp);
         ans=add(ans,b);
    
         return ans;
    
       }
       else
       {
           matrix b=quick_mod(n/2);
           matrix  ans=temp;
           ans=multi(ans,b);
           ans=add(ans,temp);
           return ans;
    
       }
    // 或者这种写法
    //   if(n&1)
    //   {
    //       b=quick_mod(n/2+1);
    //       temp=add(temp,multi(temp,b));
    //       temp=add(temp,b);
    //
    //
    //   }
    //   else
    //   {
    //      b=quick_mod(n/2);
    //      temp=add(temp,multi(temp,b));
    //
    //   }
    //   return temp;
    
    }
    int main()
    {
    
    
       int k;
       cin>>n>>k>>M;
    
       init();
    
       matrix ans;
       ans=sum(k);
    
      for(int i=0;i<n;i++)
        {
          for(int j=0;j<n-1;j++)
           cout<<ans.m[i][j]<<" ";
           cout<<ans.m[i][n-1]<<endl;
        }
    
    
    }
    





  • 相关阅读:
    AutoCAD LISP矩形窗格绘制
    AutoCAD VBA多重延伸
    2011年3月24日星期四
    AutoCAD VBA对齐对象
    AutoCAD VBA根据对象缩放
    AutoCAD LISP绘制多个等半径圆相切
    AutoCAD LISP利用一顶点和三边长绘制三角形
    AutoCAD VBA对象的组合和拆散
    AutoCAD LISP修改已存在圆半径
    AutoCAD VBA基于对象的分层
  • 原文地址:https://www.cnblogs.com/814jingqi/p/3217951.html
Copyright © 2020-2023  润新知