数据结构与算法:快速幂——求幂运算 O(logN)

前言:普通的求幂问题,相信大家已经屡见不鲜,无非就是 纯暴力 解法,或者直接调用公式:Math.Pow(底数, 指数)  一步得出。但这两种算法只能使得时间复杂度保持在 O(n)。而且公式一步的得往往对求模问题解决不了。对最大值得限制和对时间复杂度的限制,有必要让你学习一下快速幂算法。

题目:求 m 的 n 次方,对 998244353 求余。要求时间复杂度 O(logN)。

常见方法

1.暴力求
       时间复杂度 : O(n) 。

2.数学公式
       Math.Pow(m, n);(对于求模往往会出问题)。

 时间复杂度 : O(n) 。

3.快速幂算法
       时间复杂度为: O(log n)。
 

讲解:利用公式 m^{n} = (m^{2} )^{\frac{n}{2}} ,可以直接用底数的平方,指数除以2的方式,这样指数降到0只需要 log(n) 次 ,因此 时间复杂度 仅需要 O(log n) 比朴素的模拟乘方法 O(n) 优秀的多。

测试代码(c#语言):

递归方法:

  static long Recursion(long m,long n,long p)
        {
            if (n == 0) return 1;  
            if (n == 1) return m;
            long part = Recursion(m, n / 2, p);  //递归到最小,然后以此扩大到原数。 
            if(n%2==0)    //判断是否n为奇数
            {
                return part * part % p;
            }
            else
            {
                return m * part * part % p;
            }
        }
对递归函数举例解释:例如  m = 3,n=5;
第一次进入函数: n = 5, 
第二次进入函数:  n = 2  ( 5/2 = 2)  
第三次进入函数:  n = 1  ( 2/2 = 1)    返回m ,即 返回 3,
使得第二次进入函数时 part 为 3, 此时 n = 2 为偶数 ,返回 part * part 即 3*3= 9; 
使得第一次进入函数时 part 为 9, 此时 n = 5 为奇数,返回 m*part*part 即 3*9*9 得243

 非递归方法:

 static long UnRecursion(long m, long n,long p)
        {
            long res = 1;
            while(n>=1)
            {
                if (n % 2 == 1) res = res * m % p;
                n /= 2;
                m = m * m % p;
            }
            return res;
        }

两种方法具体选择看自身喜好,时间复杂度均为 logn

主测试代码:

 static void Main()
        {
            //求 m 的 n 次方,对 998244353 取余。 
            Console.WriteLine("题目:求m的n次方,对998244353求余。要求时间复杂度O(logN)。");
            Console.WriteLine("请属于m和n:");
            string[] s = Console.ReadLine().Split(' ');
            long m = Convert.ToInt64(s[0]);
            long n = Convert.ToInt64(s[1]);
            long p = 998244353;
            //直接求幂:时间复杂度O(n):
            Console.WriteLine("运用求幂公式直接得(超过最大值报错):"+Math.Pow(m, n)%p);

            Console.WriteLine("                      调用递归结果:" + Recursion(m, n, p));

            Console.WriteLine("                调用非递归递归结果:" + UnRecursion(m, n, p));

            Console.Read();
        }

测试结果截图:

3的5次方测试:

16的25次方测试: 

 当结果不超过最大值时,运行结果一致。可以得出 快速幂算法 的正确性。

可以结合例题更好的理解与学习:Leetcode:JZ83 剪绳子(进阶版)

希望本文章可以帮助到正在学算法的你,若觉得本文文章不错,希望点赞收藏,若文章有错误或者不明白的地方,欢迎交流讨论~~

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值