快速幂模板及讲解

(这篇其实是我用来练习公式编辑器滴,所以讲的内容略水,大佬们也赏脸看看吧)

定义

快速幂即快速求幂(下文为求a的x次幂模m的结果),但我们一般只在要求对一个数的幂取模时才使用,因为有可能结果很大,有可能long long都存不下,但是因为我们有:

\((ab)\%m=(a\%m)(b\%m)\)

通过转换,可得:

\((a^x)\%m\)

\(= (a\times a\times a\times …\times a(共x个a相乘))\%m\)

\(= (a\%m)\times (a\times a\times a\times …\times a(共x-1个a相乘))\%m\)

\(=((a\%m)\times a\%m)\times (a\times a\times a\times …\times a(共x-2个a相乘))\%m\)

\[……\]

按照这个规律可以一直分解下去,有点类似递归的思想,这样对没一次乘都取模,计算的过程中就不会内存爆炸了

但是只按照上面的方法分解时间复杂度是\(O(x)\),明显不够优秀(摊手手),快速幂一般那个\(x\)都是极其变态滴,比如x都是\(10^8\)级别的,或者有时候还要求很多次的快速幂,这个复杂度明显凉了,但是我们正统的快速幂算法只要\(O(log(x))\)的时间复杂度,这样就算x真的取\(10^8\)也才\(O(27)\)是不是贼快,接下来我就来介绍一下怎么实现

思路

先来说说递归的思路:

int modpow(int a,int x,int mod){……}

表示求a的x次幂,结果对mod取这个算法的核心就是用平方的方法来省事

如果x为偶数,设\(x=2\times k\),

则 \(a^x=a^{2k}=(a^k)^2\)

然后递归调用modpow(a,x/2,mod)就可以得到\(a^k\),

定义一个新变量(比如tmp)把这个结果存储起来

然后tmp=(tmp\times tmp)%mod;

此时的tmp就是\(a^{2k}\)即\(a^x\)

如果x为奇数,设\(x=2\times k+1\),

则 \(a^x=a^{2k+1}=(a^k)^2\times a\)

\(a^{2k}\)还是要求的,所以上面的步骤还是要做(因为是整除,所以x/2在这里于是等于k)

所以可以在上面的步骤做完后判断一下

if(x%2==1)//即x为奇数

tmp=(tmp*a)%mod;

特别的,如果x为0,立刻返回1(这个肯定没毛病吧)

于是我们的快速幂递归版就闪亮登场了:

int modpow(int a,int x,int mod)//求a的x次幂的递归法,结果对mod取模
{
  if(x==0)
    return 1;
  int tmp=modpow(a,x/2,mod);
  tmp=(tmp*tmp)%mod;//这里tmp就已经是a的2k次幂
  if(x%2==1)//如果x是奇数
    tmp=(tmp*a)%mod;
  return tmp;
}
然后是非递归思路:

这个方法比较玄学,可以参考一下(我还是比较喜欢递归法)

核心思路是这样的,我们把x转换为二进制,答案初值赋为1,然后如果从右往左数第k位是1,就把答案乘上\(a^{k^2}\),同时在枚举二进制下的x的位数时可以顺便把\(a^{k^2}\)搞了,可以用一个while实现以上步骤,复杂度同样是\(O(log(x))\)(是不是听不懂,没关系看看代码吧):

int poww(int a,int x,int mod){//求a的x次幂的非递归法,结果对mod取模
  int ans=1,base=a;
  while(x>0){
    if(x%2==1)//如果当前这位为1
      ans=(ans*base)%mod;
    base=(base*base)%mod;//这里处理的是a的2k次幂
    x/=2;//这样下一次处理的就是x在二进制下的下一位
  }
  return ans;
}

OK这篇模板讲解就到这咯,一般不会有题目会要求直接求快速幂,可能会换个马甲,也有时候会是一道综合的题目里一个小部分,反正就是不用当心求a的x次方时会超时或超内存,快速幂很优秀

原文地址:https://www.cnblogs.com/fjyyc/p/9215603.html

时间: 2024-11-08 21:02:04

快速幂模板及讲解的相关文章

矩阵快速幂 模板与简单讲解

模板 快速幂模板 1 void solve(matrix t,long long o) 2 { 3 matrix e; 4 5 memset(e.a,0,sizeof(e.a)); 6 7 for (int i = 0;i < d;i++) 8 e.a[i][i] = 1; 9 10 while (o) 11 { 12 if (o & 1) 13 { 14 e = mul(e,t); 15 } 16 17 o >>= 1; 18 19 t = mul(t,t); 20 } 21

51nod1113(矩阵快速幂模板)

题目链接:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1113 题意:中文题诶- 思路:矩阵快速幂模板 代码: 1 #include <iostream> 2 #define ll long long 3 using namespace std; 4 5 const int mod = 1e9+7; 6 const int MAXN = 1e2+10; 7 int n, m; 8 9 typedef struct

矩阵快速幂模板篇

转载请注明出处:http://blog.csdn.net/u012860063 或许你们看不太懂,纯属自用: 第一种: Description Let's define another number sequence, given by the following function: f(0) = a f(1) = b f(n) = f(n-1) + f(n-2), n > 1 When a = 0 and b = 1, this sequence gives the Fibonacci seq

矩阵快速幂 模板

矩阵快速幂模板 1 #include<stdio.h> 2 #include<math.h> 3 #include<set> 4 #include<string.h> 5 using namespace std; 6 int const mod=1e9+7; 7 struct matrix 8 { 9 long long m[3][3]; 10 matrix() 11 { 12 memset(m,0,sizeof(m)); 13 } 14 matrix op

POJ 1995 Raising Modulo Numbers (快速幂模板)

Raising Modulo Numbers Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 4938   Accepted: 2864 Description People are different. Some secretly read magazines full of interesting girls' pictures, others create an A-bomb in their cellar, oth

快速幂和矩阵快速幂模板

快速幂模板: ll qmod(ll x,ll n,ll mod) { ll res=1; while(n){ if(n&1) res=(res*x)%mod; x=(x*x)%mod; n/=2; } return res; } 例题:hdu 1097 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> usin

HDU1575--Tr A(矩阵快速幂模板)

Tr A Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据. 每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据.接下来有n行,每行有n

hdu-1757 A Simple Math Problem---矩阵快速幂模板题

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1757 题目大意: 求递推式第k项模m If x < 10 f(x) = x.If x >= 10 f(x) = a0 * f(x-1) + a1 * f(x-2) + a2 * f(x-3) + -- + a9 * f(x-10);And ai(0<=i<=9) can only be 0 or 1 . 解题思路: 构建矩阵 直接用矩阵快速幂模板求解 注意,小于10的时候不能直接输出

HDU-1575-Tr A(矩阵快速幂模板)

Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973. Input 数据的第一行是一个T,表示有T组数据. 每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据.接下来有n行,每行有n个数据,每个数据的范围是[0,9],表示方阵A的内容. Output 对应每组数据,输出Tr(A^k)%9973. Sample Input 2 2 2 1 0 0 1 3 99999