乘方取模,矩阵快速幂简单模板

一.乘法快速取余

算a*b%n

//乘法快速幂a*b%n,不写连乘是防止相乘时溢出
__int64 multi(__int64 a,__int64 b,__int64 n)
{
    __int64 temp = 0;
    while(b!=0)
    {
        if(b%2==1)
        {
            temp+=a;
            if(temp>=n)
                temp-=n;
        }
        a*=2;
        if(a>=n)
            a-=n;
        b/=2;
    }
    return temp;
}

 

 

二.乘方取模

算a^n%m

定理:要计算只包含加减乘的整数表达式除以整数m的余数时,可以在每步计算时对m取余

容易想到的代码如下:

int ans = 1;
for(int i=1;i<=n;i++)
  ans=ans*a%m;

这样做时间发杂度为O(n),如果n=10^9,那么肯定会超时;

优化后的代码:

 1 __int64 mutimod(__int64 a,__int64 n,__int64 m)
 2 {
 3     __int64 ans=1;
 4     while(n)
 5     {
 6         if(n&1LL)//判断是否为奇数
 7             ans=ans*a%m;
 8         n>>=1LL;
 9         a=a*a%m;
10     }
11     return ans;
12 }
  
//乘方快速幂a^n%m
__int64 multimod(__int64 a,__int64 n,__int64 m)
{
    __int64 ans=1;
    while(n!=0)
    {
        if(n%2==1)
            ans=multi(ans,a,m);
        a=multi(a,a,m);
        n/=2;
    }
    return ans;
}

 

 

三.矩阵快速幂

A是一个矩阵,求A^n;

代码如下:

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int mod = 10000;
const int N = 2;//矩阵的维数,角标从0开始
struct Matrix
{
    __int64 v[N][N];
    Matrix()
    {
        memset(v,0,sizeof(v));
    }
};
//矩阵的乘法p1*p2
Matrix multi(Matrix p1,Matrix p2)
{
    Matrix res;
    for(int i=0;i<N;i++)
        for(int j=0;j<N;j++)
            if(p1.v[i][j])//代码优化,是0的话就不用计算
                for(int k=0;k<N;k++)
                    //根据具体需要修改mod
                    res.v[i][k]=(res.v[i][k]+(p1.v[i][j]*p2.v[j][k]))%mod;
    return res;
}
//矩阵的快速幂p^k
Matrix pow(Matrix p,__int64 k)
{
    Matrix t;
    for(int i=0;i<N;i++)//初始化为单位矩阵
        t.v[i][i]=1;
    while(k)
    {
        if(k&1)
            t=multi(t,p);
        p=multi(p,p);
        k=k>>1;
    }
    return t;
}

 

posted on 2016-08-09 16:06  wastonl  阅读(621)  评论(0编辑  收藏  举报