快速幂和矩阵快速幂

来源:互联网 发布:python3进行数据分析 编辑:程序博客网 时间:2024/06/01 09:36

这篇博客讲的比较详细,关于快速幂和矩阵快速幂的。

http://blog.csdn.net/hikean/article/details/9749391

快速幂

快速幂就是计算a^n时,能使复杂度从O(n)降到O(logn)。
它的原理是这样的:
将n写成2进制形式,比如,求a^9。9的二进制写法为 1001,即
从最后一位开始看,是1,所以计算a^1,并加入到结果中,然后看倒数第二位,为0,只计算a^2,然后看倒数第三位,是0,同样只计算a^4,这时只需要利用上面的a^2结果,进行一次乘法即可。再看倒数第四位,为1,就计算a^8,并将其加入到最后结果中,只需要利用前面的a^4进行一次乘法计算即可。这样,结果中就是a^9的数了。
下面直接用代码说明它的意思:

#include <iostream>#include <algorithm>#include <string>using namespace std;#define mod 1000000007  //一般数都会很大,所以取模  而且类型都是long long类型的long long pow(int base, int n) //要计算 base^n{    long long ans = 1;    long long multi = base;    long long temp = n;    while (temp > 0)    {        if (temp % 2 == 1)            ans = (ans * multi);        ans %= mod;        multi *= multi;        multi %= mod;        temp /= 2;    }    return ans;}int main(){    int base = 5, n = 3;  //求base^n    cout << pow(5, 10000) << endl;    return 0;}

矩阵快速幂

矩阵快速幂就是求矩阵的n次方,也使复杂度大大降低。一般这种情况下都会有一个递推式,比如斐波那契数列f(n)=f(n-1)+f(n-2).

这里写图片描述
所以,计算那个矩阵的n-1次方,然后确定出f(1)和f(2)的系数,就可以快速求出f(n)。
但是,这种斐波那契递推式是最简单的,很多题目中会加一些变量,题目的难点就是确定出这个矩阵。
比如:f(n)=f(n-1)+f(n-2)+n^3。这需要先推导一下,使
n^3=(n-1+1)^3=(n-1)^3+3*(n-1)^2+3*(n-1)+1
这里写图片描述
根据上述公式,确定要求的矩阵的幂指数,然后组合一下,就可以得到f(n)了。矩阵快速幂的代码在最下面给出。
除了这种递推式,还有一种类型是求前n项和。比如像上题,不要求求f(n),而是求f(1)+f(2)+……f(n),这样只需要在两个向量的最下边加上sum,构造一个7*7的矩阵,就可以了。还有那种求第i项到第n项的和,这时可以求S(n)-S(i-1),把它当做递推式。
下面代码是刚才6*6矩阵的那个题:

#include <iostream>#include <algorithm>#include <string>using namespace std;#define mod 1000000007  //一般数都会很大,所以取模  而且类型都是long long类型的#define num 6struct matrix //定义矩阵{    long long a[num][num];    void init(){        memset(a, 0, sizeof(a));        for (int i = 0; i < num; i++)            a[i][i] = 1;   //初始化为单位矩阵    }};matrix mul(matrix x, matrix y){    matrix c;    for (int i = 0; i < num; i++)    {        for (int j = 0; j < num; j++)        {            long long temp = 0;            for (int k = 0; k < num; k++)            {                temp += x.a[i][k] * y.a[k][j];                temp %= mod;            }            c.a[i][j] = temp%mod;        }    }    return c;}matrix pow(matrix base, long long n) //要计算 base^n{    matrix ans;    ans.init();  //首先初始化为方阵    matrix multi = base;    long long temp = n;    while (temp > 0)    {        if (temp % 2 == 1)            ans = mul(ans, multi);        multi = mul(multi, multi);        temp /= 2;    }    return ans;}int main(){    matrix base;//  {{ 1, 1, 1, 3, 3, 1 },//  { 1, 0, 0, 0, 0, 0 },//  { 0, 0, 1, 1, 1, 1 },//  { 0, 0, 0, 1, 2, 1 },//  { 0, 0, 0, 0, 1, 1 },//  { 0, 0, 0, 0, 0, 1 } };    base.init();  //对数组赋值,只能一个个赋值了,但是因为之前初始化为了方阵,所以可以减轻工作量    base.a[0][0] = base.a[0][1] = base.a[0][2] = base.a[0][6] = base.a[1][0] = base.a[2][2] = base.a[2][3] = base.a[2][4] = base.a[2][5] = base.a[3][3] = base.a[3][5] = base.a[4][4] = base.a[4][5] = base.a[5][5] = 1;    base.a[0][3] = base.a[0][4] = 3;    base.a[3][4] = 2;    base.a[1][1] = 0;       long long n = 440;  //求base^n    matrix t = pow(base, n);    long long fn = 0;    int fn1 = 5, fn2 = 4, n3 = 1, n2 = 6, n1 = 8, n00 = 5;    int f[num] = { fn1, fn2, n3, n2, n1, n00 };    for (int i = 0; i < num; i++)    {        fn += t.a[0][i]%mod * f[i]%mod;        fn %= mod;    }    cout << fn << endl;    return 0;}
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 草莓被蚂蚁吃了怎么办 脖子被种了草莓怎么办 2岁的宝宝说脏话怎么办 欠钱的人跑路了怎么办 美国非婚生子父亲不认怎么办 孕4个月肚子胀气怎么办 8个月孕妇感冒了怎么办 孕8个月感冒鼻塞怎么办 怀孕八个月感冒了怎么办 孕八个月咳嗽了怎么办 享物说同城自提怎么办 锤基意外怀孕怎么办 08 蛐蛐罐底翻砂了怎么办 剑网3中被盗号后怎么办 本人想离婚对方躲避怎么办 微信不能说语音怎么办 微信语音发不了怎么办 吃鸡语音用不了怎么办 要杀我的人见面怎么办 转晕了想吐怎么办 原地转圈头晕恶心想吐怎么办 孩子吃凉的呕吐头还晕怎么办 孩子转晕了想吐怎么办 转圈晕了想吐怎么办 我爸总是骂我妈怎么办 转圈转的想吐怎么办 大便干燥拉不出来怎么办 吹完头发很干燥怎么办 腿摔伤了结痂疼怎么办 蹭wifi被禁止后怎么办 电脑wifi给拉黑怎么办 电脑想用无线网怎么办 中路被对方打崩了怎么办 英雄联盟队友太坑怎么办 匹配被王者虐了怎么办 lol碰到嘴臭的怎么办 小婴儿脾气大怎么办呢? 玩游戏输入法会跳出出来怎么办 逆水寒fps太低怎么办 我dcj没地速怎么办 电焊看久眼睛疼怎么办