快速幂+快速矩阵幂学习

来源:互联网 发布:网络语鸡肋是什么意思 编辑:程序博客网 时间:2024/06/13 01:10

快速幂学习
计算3^11
如果用传统计算,则是
for(i~11)
s*=3;
速度为n
这里利用快速幂思想
3^11=3^1* 3^2* 3^8
3^1的平方就是3^2,再平方就是3^8;最后再将他们乘起来就是求出来的数了,速度也达到了log(n)。

算法中我们可以先判断幂指数是否为奇数,先乘一个3,然后对剩下的3^10指数10/2,先算出3^5,这时又出现了指数为奇数,再乘一个3,继续n/2,算出3^2,由于指数为偶数2/1算出3^1,再将他们乘起来。

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <iostream>using namespace std;long long pow3(long long a,long long b){    long long ans = 1,t= a;    while(b!=0)    {        if(b&1)//奇数时            ans *= t;        t*= t;        b>>=1;    }    return ans%100000007;}int main(){    cout<<pow3(3,11)<<endl;    return 0;}

快速矩阵幂学习

POJ3070 求Fibonacci数,给你n和m,求出第n个斐波拉契数mod(m)的结果

思路和快速幂是一样的,不过多加了一个矩阵相乘函数

///POJ3070求Fibonacci数#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <iostream>//#define mod 10000using namespace std;typedef struct{    int arr[2][2];} matrix;matrix multi(matrix a,matrix b)//矩阵相乘{    matrix d;    memset(d.arr,0,sizeof(d.arr));    for(int i=0; i<2; i++)    {        for(int j=0; j<2; j++)        {            for(int k=0; k<2; k++)                d.arr[i][j]+=a.arr[i][k]*b.arr[k][j];            d.arr[i][j]%=mod;        }    }    return d;}matrix doublemult(matrix a,int b)///矩阵幂{    matrix mm,vv;    mm.arr[0][0]=1;    mm.arr[0][1]=0;    mm.arr[1][0]=0;    mm.arr[1][1]=1;    vv=a;    if(b==0)        return mm;    else    {        while(b!=1)        {            if(b&1)            {                b--;                mm=multi(mm,vv);            }            else            {                b/=2;                vv=multi(vv,vv);            }        }        return multi(mm,vv);    }}int main(){    int n;    int mod;    matrix fib,res;    fib.arr[0][0]=1;    fib.arr[0][1]=1;    fib.arr[1][0]=1;    fib.arr[1][1]=0;    while(scanf("%d%d",&n,&mod)!=EOF)    {        res=doublemult(fib,n);        cout<<res.arr[0][1]%mod<<endl;    }    return 0;}

题目
poj3233求A^1+A^2+A^3+A^4+A^5+A^6 输出的数据mod m。k<=10^9。

可以将式子二分优化:=A^1+A^2+A^3+A^3(A^1+A^2+A^3)
再分别递归A^1,A^2,A^3,计算出总和。

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#include <queue>#include <iostream>using namespace std;int n,m;typedef struct{    int arr[60][60];}matrix;matrix multi(matrix a,matrix b){    matrix d;    for(int i=0;i<2*n;i++)    {        for(int j=0;j<2*n;j++)        {            for(int k=0;k<2*n;k++)            {                d.arr[i][j]=(d.arr[i][j]+a.arr[i][k]*b.arr[k][j])%m;            }        }    }    return d;}matrix doublemult(matrix a,int k){    matrix mm,vv;    memset(mm.arr,0,sizeof(mm.arr));    for(int i=0;i<n;i++)    {        mm.arr[i][i]=1;    }    vv=a;    if(k<=0)    return mm;    else    {        while(k!=1)        {            if(k&1)            {                k--;                mm=multi(mm,vv);            }            else            {                k/=2;                vv=multi(vv,vv);            }        }        return multi(mm,vv);    }}int main(){    matrix A,B,C;    int k;    while(scanf("%d%d%d",&n,&k,&m)!=EOF)    {        memset(A.arr,0,sizeof(A.arr));        for(int i=0;i<n;i++)        {            for(int j=0;j<n;j++)            {                scanf("%d",&A.arr[i][j]);            }        }        memcpy(B.arr,A.arr,sizeof(A.arr));        for(int i=0;i<n;i++)        for(int j=0;j<n;j++)        {            A.arr[i][j+n]=A.arr[i][j];        }        for(int i=n;i<2*n;i++)        {            A.arr[i][i]=1;            B.arr[i][i-n]=1;        }        C=multi(doublemult(A,k-1),B);        for(int i=0;i<n;i++)        {            for(int j=0;j<n-1;j++)            printf("%d ",C.arr[i][j]);            printf("%d\n",C.arr[i][n-1]);        }    }    return 0;}
原创粉丝点击