快速幂-demo

原创 2016年08月28日 20:59:16

问题描述

本文主要给出快速幂以及快速幂结合求模操作的一般方法

思路

当幂的数字太大时,计算的次数较大。
需要简化计算,可以采用快速幂。
二分幂的办法。

下面这是一种思路:
当b较大时,将其进行分解。

1. b为偶数时,a^b = a^(b/2) * a^(b/2)
2. b为奇数时,a^b = a^(b/2) * a^(b/2) * a

可用递归实现。
如果用非递归可在递归的基础上进行修改。但是要小心奇数和偶数的区别。
所以,还是要借助一个栈来实现。效率并不高。

下面讲另外一种思路:
主要思路是:
将a^b分解为若干个a^(2^k)项的乘积,也体现了分治的思想。
具体来说是在指数层面,将b分解为若干项(2^k)的和。

比如下面的例子:
3 ^ 999 = (3 ^ 512) * (3 ^ 256) * (3 ^ 128) * (3 ^ 64) * (3 ^ 32) * (3 ^ 4) * (3 ^ 2) * 3
= 3 ^ (512 + 256 + 128 + 64 + 32 + 4 + 2 + 1)

对于指数b的分解本质是求b的二进制形式
之所以写成二进制形式的好处是,前一位都可以由后一位的乘积构成。注意这里已经不是在指数层面了。
怎么判断哪一位的权出现,就看分解后相应二进制位是否有效。

看下面的问题: [ jobdu-1441]

题目描述:
求A^B的最后三位数表示的整数。说明:A^B的含义是“A的B次方”
输入:
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。
输出:
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。
样例输入:
2 3
12 6
6789 10000
0 0
样例输出:
8
984
1

方法一

 int fast_pow( int a, int b, int mod )
{
    if(1==b)
        return a%mod;
    else
    {
        int t = fast_pow( a, b/2, mod );
        if( b%2 )
            return ((t%mod)*(t%mod)*(a%mod))%mod;
        else
            return ((t%mod)*(t%mod))%mod;
    }
}
int fast_pow_without_recursion( int a, int b, int mod )
{
    std::stack<int> stk;
    while( b > 1 )
    {
        stk.push(b%2);
        b /= 2;
    }

    int ans = a%mod;
    while( !stk.empty() )
    {
        int t = stk.top();
        stk.pop();

        if(t%2)
            ans = (ans%mod * ans%mod * a%mod)%mod;
        else
            ans = (ans%mod * ans%mod)%mod ;
    }
    return ans;
}

方法二

int fast_pow1( int a, int b, int mod )
{
    int ans = 1;
    int w = a;
    while( b )
    {
        if(b%2)
            ans = (ans * w%mod)%mod;
        w *= w;
        b /= 2;
    }
    return ans;
}

这个方法,看起来逻辑并没有问题。但是在调试的时候最后一组数据没有过。

1. 边界数据的问题
2. 中间值w*w过大

仔细分析后发现,由于每一个中间项都是由前一项平方得来。所以,加载这一项的求mod。
可以移到前面去。并且,最后一组数据爆了的原因就是,a很大之后w*w很容易直接爆掉。
所以,把求mod放在这里是正确的。应该可以解决之前的问题。

int fast_pow2( int a, int b, int mod )
{
    int ans = 1;
    int w = a;
    while( b )
    {
        if(b%2)
            ans = (ans * w)%mod;
        w = (w%mod * w%mod)%mod;
        b /= 2;
    }
    return ans;
}

总结

刷题一定要有耐心,就像对于方法二。满怀信心,觉得逻辑没有任何错误。但是还是有问题。不能直接百度,一定要自己反复思考,别害怕浪费时间。出来混的早晚都是要还的。虽然最后一点想了好久,但是最后还是想出来了,现在看来也许是轻而易举的事,但是你没到那个程度肯定是不行的。有问题是好事,有问题就能提高。享受解决问题的过程,这就是游戏,看你怎么玩。


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

安卓NFC标签读取快速开发教程(附源代码demo下载)

Demo下载 1.NFC的工作模式 NFC支持如下3种工作模式:读卡器模式(Reader/writer mode)、仿真卡模式(Card Emulation Mode)、点对点模式(P2P...

【Android】如何快速构建Android Demo

欢迎使用Markdown编辑器写博客本Markdown编辑器使用StackEdit修改而来,用它写博客,将会带来全新的体验哦: Markdown和扩展Markdown简洁的语法 代码块高亮 图片链接和...
  • xesam
  • xesam
  • 2016年04月09日 13:47
  • 224

AspNet MVC4 教学-18:Asp.Net MVC4 客户端验证和服务端验证快速Demo

Asp.Net MVC4 客户端验证和服务端验证快速Demo

AspNet MVC4 教学-23:Asp.Net MVC4 Display And Editor 模板技术快速应用Demo

Asp.Net MVC4 Editor 模板技术快速应用Demo

AspNet MVC4 教学-11:Asp.Net MVC4 默认Authorize及自定义Authorize快速Demo

Asp.Net MVC4 默认Authorize及自定义Authorize快速Demo

AspNet MVC4 教学-28:Asp.Net MVC4 Ajax技术实现除法取整取余快速Demo

Asp.Net MVC4 Ajax技术实现除法取整取余快速Demo

快速掌握SuperMap 3D Viewer演示Demo

SuperMap 3D Viewer演示Demo使用说明 **作者:xinxin       在各大Android APP Store 和 iPhone Store上可以下载和安装一个基于Supe...

React实战-如何快速构建一个ReactNative的Demo

React实战-如何快速构建一个ReactNative的Demo ReactJs宣称的是一次学习就够了,意思是学习了ReactJs后,在Web端和移动端就都一样处理了。事实是否真的是这样呢?在实际的应...

android app --- 快速集成SMS实现短信验证(二)2.0版之后(附注册验证demo)

之前写过一篇android app --- 快速集成SharaSDK ,SMS实现短信验证(一)2.0版之前 ,2.0之前官方没有对android studio 做支持,集成起来需要技巧,比较麻烦。 ...

Android AIDL -通过一个比较完整的Demo快速运用

前端时间项目运用到AIDL,关于AIDL客户端以及AIDL服务端网络上没有一个比较完备的Demo. 而参考Demo无疑是一个比较快速的学习方法.因此,我写了一个Demo. 供大家参考,也非常欢迎大...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:快速幂-demo
举报原因:
原因补充:

(最多只允许输入30个字)