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;
    }
  • 相关阅读:
    Python生成器
    Python函数之传参
    前端之HTML
    联合分组、子查询、视图、事务、python操作mysql、索引
    单表查询和连表查询具体操作
    字段详细操作、多表关系、外键关联和级联关系以及增、删、改的操作
    数据库与表的其他操作、字段的操作、数据类型、字段的约束条件
    协程
    初识数据库
    线程Queue、定时器、进程池和线程池、同步异步
  • 原文地址:https://www.cnblogs.com/wt20/p/5753596.html
Copyright © 2011-2022 走看看