zoukankan      html  css  js  c++  java
  • 乘方取模,矩阵快速幂简单模板

    一.乘法快速取余

    算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;
    }
  • 相关阅读:
    linux服务器安装nginx及使用
    服务器搭建
    Linux安装mysql5.7
    个人服务器的选择
    DECODE函数简介
    ORACLE数据库优化
    Mac下JD-GUI无法使用
    Qt 中QString 字符串操作:连接、组合、替换、去掉空白字符
    [Qt初级] 解决 中QMainWindow和QDockWidget添加布局失败问题
    我的JS 中级学习篇
  • 原文地址:https://www.cnblogs.com/wt20/p/5753596.html
Copyright © 2011-2022 走看看