zoukankan      html  css  js  c++  java
  • 幂运算

    幂运算

    众所周知,在NOIP系列竞赛中,会考到许多优化,而这些许多优化是由一个个简单的优化组件而来的,使整个程序的优化尽可能地达到最大,用最少的时间和空间来实现正确代码,而幂运算作为其中的一个基本我今天就来总结一下,如有不足,以后也会加勘误and Update。

    普遍数学上幂的意义是一个数做自乘的运算,如a的b次方意思是b个a相乘,使表示上更加简便

    普通幂

    C++中普通幂的代码很容易实现,这是实现代码(基本实现代码)

    #include <iostream>
    using namespace std;
    int main()
    {
        int a,b;
        cin>>a>>b;
        for(int i=2;i<=b;i++)
        a*=a;
        cout<<a<<endl;
        return 0;
    }
    

    快速幂

    在普通幂中发现算很大的数的时候回非常地慢,我们就要想怎么优化,怎么优化呢,我们引入一组基本公式

    [a^b=a^{frac{b}{2}}*a^{frac{b}{2}}(b为偶数) ]

    [a^b=a^{frac{b}{2}}*a^{frac{b}{2}}*a(b为奇数) ]

    我们发现这样可以利用递归解决子问题来快速地算出a的b次方,加速了运算

    代码如下

    #include <iostream>
    using namespace std;
    int a,b;
    int quick_pow(int a,int b)
    {
        if(b==0)
            return 1;
        int t=quick_pow(a,b/2);
        if(b%2==1)
            return t*t*a;
        else
            return t*t;
    }
    int main()
    {
        cin>>a>>b;
        cout<<quick_pow(a,b)<<endl;
        return 0;
    }
    

    或者代码也可以这样

    #include <iostream>
    using namespace std;
    int power(int a,int b,int p)
    {
    	int ans=1%p;
    	while(b)
    	{
    		if(b&1)
    		ans=(long long)ans*a%p;
    		a=(long long)a*a%p; 
            b>>=1;
    	}
    	return ans;
    }
    int main()
    {
    	int a,b,p;
    	cin>>a>>b>>p;
    	cout<<power(a,b,p)<<endl;
    	return 0;	
    } 
    

    特殊情况下算2的n次幂可以直接

    [1<<n ]

    矩阵快速幂

    矩阵快速幂是一个对于矩阵的快速幂

    你还不知道什么是矩阵吗?(快速查看:矩阵

    矩阵快速幂是对于矩阵乘法的自己多次相乘的快速运算

    和普通快速幂差不多,只是把‘*’换成了一个mul函数

    代码如下

    mat mul(mat x,mat y)
    {
    	mat c;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		c.m[i][j]=0;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			for(int k=1;k<=n;k++)
    			c.m[i][j]=(c.m[i][j]%mod+(x.m[i][k]*y.m[k][j])%mod)%mod;
    		}
    	}
    	return c;
    }
    

    因为要返回一个数组,所以为了方便,我们新建了一个结构体,也就是mat

    struct mat
    {
        long long m[1005][1005];//用来存矩阵
    };
    

    这样我们在写一个类似于普通快速幂的函数就成功解决问题了

    类普通快速幂函数

    mat pow(mat a,long long b)
    {
    	mat ans=e;
    	while(b)
    	{
    		if(b&1)
    		ans=mul(ans,a);
    		a=mul(a,a);
    		b>>=1;
    	}
    	return ans;
    }
    

    所以我们就做出来了,但是为了使整个矩阵能保持原样,这个说不清,自己去看单位矩阵,然后这就是一个巧妙的地方

    for(int i=1;i<=n;i++)
    	e.m[i][i]=1;
    

    最后,矩阵快速幂的一道模板题发给大家


    lgP3390【模板】矩阵快速幂

    提交 25.45k

    通过 8.58k

    时间限制 1.00s

    内存限制 125.00MB

    题目背景

    矩阵快速幂

    题目描述

    给定n*n的矩阵A,求A^k

    输入格式

    第一行,n,k

    第2至n+1行,每行n个数,第i+1行第j个数表示矩阵第i行第j列的元素

    输出格式

    输出A^k

    共n行,每行n个数,第i行第j个数表示矩阵第i行第j列的元素,每个元素模10^9+7

    输入输出样例

    输入 #1

    2 1
    1 1
    1 1
    

    输出 #1

    1 1
    1 1
    

    说明/提示

    n<=100, k<=10^12, |矩阵元素|<=1000 算法:矩阵快速幂


    AC代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    const int maxn=1005;
    const int mod=1000000007; 
    struct mat
    {
    	long long m[maxn][maxn];
    };
    mat a,e;
    long long n,p;
    mat mul(mat x,mat y)
    {
    	mat c;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		c.m[i][j]=0;
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		{
    			for(int k=1;k<=n;k++)
    			c.m[i][j]=(c.m[i][j]%mod+(x.m[i][k]*y.m[k][j])%mod)%mod;
    		}
    	}
    	return c;
    }
    mat pow(mat a,long long b)
    {
    	mat ans=e;
    	while(b)
    	{
    		if(b&1)
    		ans=mul(ans,a);
    		a=mul(a,a);
    		b>>=1;
    	}
    	return ans;
    }
    int main()
    {
    	cin>>n>>p;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		cin>>a.m[i][j];
    	}
    	for(int i=1;i<=n;i++)
    	e.m[i][i]=1;a
    	mat s=pow(a,p);
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++)
    		cout<<s.m[i][j]<<" ";
    		cout<<endl;
    	}
    	return 0;
    }
    

    PS:在自己电脑上可能输出不了,但是在洛谷IDE上能正常运行啊

    这就奇怪了,请问一下各位为什么

    下集预告:单源最短路径的优化或矩阵的简单介绍

    本博文为wweiyi原创,若想转载请联系作者,qq:2844938982
  • 相关阅读:
    SQL COUNT() 语法
    SQL AVG 函数
    Android开发
    IIf 函数
    励志
    王者归来
    Java基础知识总结(绝对经典)
    LeetCode算法题-Third Maximum Number(Java实现-四种解法)
    LeetCode算法题-Fizz Buzz(Java实现)
    LeetCode算法题-Longest Palindrome(五种解法)
  • 原文地址:https://www.cnblogs.com/wweiyi2004/p/11294675.html
Copyright © 2011-2022 走看看