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

    在我们求一些递推式子是,如果一味的使用for可能在数据很大的时候就超时,所以引入矩阵快速幂

    将递推关系隐藏在初始矩阵中,然后使用矩阵快速幂降低时间,就可求出

    https://www.luogu.org/problem/P3390

    /*
        Name:
        Copyright:
        Author:  流照君
        Date: 2019/8/12 15:05:21
        Description:
    */
    #include <iostream>
    #include<string>
    #include <algorithm>
    #include <vector>
    #include<cstring> 
    #define inf 100
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    ll n;
    struct matrix{
    	ll a[inf][inf];//构造函数 
    	    matrix(){
    		memset(a,0,sizeof(a));
    	}
    	inline void bulid()//初始化 
    	{
    		for(int i=1;i<=n;i++)
    		a[i][i]=1;
    	}
    };
    matrix ma,unit;
    matrix operator*(const matrix &x,const matrix &y)//重载运算符 
    {
    	matrix ans;
    	for(int k=1;k<=n;k++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    			{
    				ans.a[i][j]=(ans.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
    			}
    			return ans;
    }
    matrix pow(matrix ma1,ll k) 
    {
    	matrix ans;
    	ans.bulid();
    	do
    	{
    		if(k&1)
    		ans=ans*ma1;
    		ma1=ma1*ma1;
    		k=k/2;
    	}while(k);
    	return ans;
    }
    int main(int argc, char** argv)
    {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        ll k; 
        scanf("%lld %lld",&n,&k);
        for(int i=1;i<=n;i++)
        {
        	for(int j=1;j<=n;j++)
        	{
        		scanf("%lld",&ma.a[i][j]);
        	}
    	}
    	unit.bulid();
    	matrix res=pow(ma,k);
    	for(int i=1;i<=n;cout<<endl,++i)
            for(int j=1;j<=n;++j)
                printf("%lld ",res.a[i][j]);
        return 0;
    }
    

      其中乘法可以不重载,而使用函数

    转载一段话————————————————————————————————————————————————————————————————————

     那么,矩阵乘法的优越性究竟体现在哪里呢。其实,矩阵乘法只是体现了我们从之前求的数到现在要求的数的递推过程,就是说矩阵乘法可以完成多个元素的递推。不过这个我们用普通的递推就可以实现的啊~~认真想想我们就能发现,我们在矩阵乘法的过程中把上见面的A矩阵自己相乘了很多遍。就是说,我们可以求A矩阵的幂最后乘上B矩阵,既然要求幂,矩阵乘法满足结合律,那么我们就可以用快速幂啦~~矩阵乘法的优越性就体现在这里:在递推过程变成不断乘以一个矩阵,然后用快速幂快速求得从第一个到第n个的递推式,这样子就可以在短时间内完成递推了。

        哇塞,人类的智商啊~~让我们继续膜拜那些智商正无穷的大神吧,orz,orz……  链接https://www.cnblogs.com/Konjakmoyu/p/4821044.html

    ——————————更新分界线——————————————————————————————————————————————————————

    看MIT线性代数才真正理解矩阵快速幂  传送门

    我们知道一个数列的递推公式  它可能不是一阶的,是很多阶的,所以这里有一个trick 就是将多阶的方程化为一阶方程组

    比如:斐波那契数列  Fk+1=Fk+Fk-1;

    我们可以改成AX 的矩阵形式     Fk+2=Fk+1+Fk;

                  Fk+1=Fk+1:

    x=[Fk+1,Fk]    发现了吗?

    于是我们找到了  [1,1;1,0]*[1,0]=[2,1]      [1,1;1,0]*[Fk+1,Fk]=[Fk+2,Fk+1] 

     在加上结合律我们就可以利用矩阵乘法就递推项了

    再加上快速幂不就缩短时间了嘛

  • 相关阅读:
    JMeter参数化及断言的使用
    JMeter基础概念
    postman关联
    postman参数化
    postman发送请求的简单操作
    postman的简单介绍及运用
    javascript小记五则:用JS写一个图片左右自由滚动的“跑马灯”效果
    javascript小记四则:用JS写一个滚动横条文字,可以根据需要进行修改;
    javascript小记三则:ASP.NET启动web调试,窗体自动放大的方法
    JavaScript小记二则:接上一节:用.net写Textbox控件关于数字的判断的另一则方法
  • 原文地址:https://www.cnblogs.com/liuzhaojun/p/11341436.html
Copyright © 2011-2022 走看看