• 快速幂 、矩阵快速幂


    快速幂

    如果要你自己写一个pow()函数,需要求2的2000000000次方,怎么求?

    int pow(int a,int b){   //普通乘
        int ans = 1;
        for(int i=1; i<=b; i++)
            ans *= a;
        return ans;
    }
    

    上述代码的时间复杂度是o(n),当数据数量级很大的时候,这份代码的耗时会非常巨大,并不能解决我们的问题。那我们该怎么办呢?
    以2的74次方为例,74的二进制为1001010。对应的,我们得到74=2+8+64。
    我们把问题转化为2的74次方 =2的2次方 * 2的8次方 * 2的64次方 。通过这个思路,这样我们把算法的复杂度降到了o(log n)。

    void Pow(long long  a,long long  b)  //快速幂 求a的b次幂
    {
    	long long s=1;
    	while(b)
    	{
    		if(b&1)	s=s*a;
    		a=a*a;
    		b>>1;
    	}
    	printf("%lld",s);
    }
    

    ``

    ``**

    矩阵快速幂

    **
    我们都知道斐波那契数列 ,而 F[N] =F[N-1]+F[N-2]。
    显然,采用递加的方式求f[n]我们需要运算 n-1次。当数据数量级很大的时候,在有限的时间内,我们是无法答案的。那么我们该怎么办呢?
    思路一:先来看斐波那契数列 ,我们先初始化三个矩阵令a[2][2]={1,1,1,0},b[2]={1,1},c[2][1]={0}。那么是不是会有 c[0][0]=a[0][0]*b[0][0]+a[0][1]*b[1][0]=1+1=2。
    c[1][0]=a[1][0]*b[0][0]+a[1][1]b[1][0]=1+0=1。
    即:
    在这里插入图片描述
    在这里插入图片描述
    乘号右侧的所有元素组成斐波那契数列的元素,我们可以用c[0][0]表示。那么我们这样做有什么好处呢?理由同快速幂,因为这样F[N]=a矩阵的n-1次方
    b矩阵 。这样一来 ,我们只不过是把底数换成了一个矩阵而已,利用上述的思路可以将时间复杂度大大降低。我们把矩阵a称为转移矩阵,用数组表示是[1,1,1,0]。最后的答案我们可以通过a的n-1次方获得。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int n,c[2][2],d[2][2],a[2][2]={1,1,1,0},b[2][2]={1,0,0,1};
    void Matrix1()
    {
    	memset(c,0,sizeof(c));
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			for(int k=0;k<2;k++)
    			{
    				c[i][j]+=b[i][k]*a[k][j];
    			}
    		}
    	}
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			b[i][j]=c[i][j];
    		}
    	}
    }
    void Matrix2()
    {
    	memset(d,0,sizeof(d));
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			for(int k=0;k<2;k++)
    			{
    				d[i][j]+=a[i][k]*a[k][j];
    			}
    		}
    	}
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			a[i][j]=d[i][j];
    		}
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	if(n==1)	printf("1");
    	else if(!n)	printf("0");	
    	else
    	{
    		n-=2;
    		while(n)
    		{
    		if(n&1)	Matrix1();
    		Matrix2();
    		n>>=1;
    		}
    		printf("%d ",b[0][0]+b[0][1]);
    	}
    	return 0;
    }
    

    思路二:

    参考思路:

    矩阵快速幂与斐波那契数列

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    int n,c[2][2],d[2][2],a[2][2]={1,1,1,0},b[2][2]={1,0,0,1};
    void Matrix1()
    {
    	memset(c,0,sizeof(c));
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			for(int k=0;k<2;k++)
    			{
    				c[i][j]+=b[i][k]*a[k][j];
    			}
    		}
    	}
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			b[i][j]=c[i][j];
    		}
    	}
    }
    void Matrix2()
    {
    	memset(d,0,sizeof(d));
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			for(int k=0;k<2;k++)
    			{
    				d[i][j]+=a[i][k]*a[k][j];
    			}
    		}
    	}
    	for(int i=0;i<2;i++)
    	{
    		for(int j=0;j<2;j++)
    		{
    			a[i][j]=d[i][j];
    		}
    	}
    }
    int main()
    {
    	scanf("%d",&n);
    	while(n)
    	{
    		if(n&1)	Matrix1();
    		Matrix2();
    		n>>=1;
    	}
    	printf("%d ",b[0][1]);
    	return 0;
    }
    



    如有不妥,欢迎指正。

  • 相关阅读:
    Proximal Gradient Descent for L1 Regularization
    使用Spring Security3的四种方法概述
    理解spring对事务的处理:传播性
    MySQL事务隔离级别详解
    Spring 使用注解方式进行事务管理
    Redis的高级应用-安全性和主从复制
    Redis的高级应用-事务处理、持久化、发布与订阅消息、虚拟内存使用
    mysql 语句优化心得
    Maven搭建Spring Security3.2项目详解
    Java网络编程之TCP、UDP
  • 原文地址:https://www.cnblogs.com/fxzemmm/p/14847979.html
Copyright © 2020-2023  润新知