NOIP中的数学--快速幂 第5课(下)

快速幂

在求a的b次方时,暴力的做法是O(b)的,而有一种高效的O(log(b))的做法———快速幂
1 、快速幂的思想
因为a2b =(a2)b,底数增加了一倍,而时间复杂度却降低了一半。快速幂就是基于这个性质的一个算法。采用分治与倍增的思想。

假设我们要求ab,那么其实b是可以拆成二进制的,该二进制数第i位的权为2(i-1),例如当b=11时,a11=a(20+21+23)
  11的二进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a(20)*a(21)*a(23) ,看出来快的多了吧,原来算11次,现在算三次,但是这三项貌似不好求的样子…不急,下面会有详细解释。
由于是二进制,很自然地想到用位运算这个强大的工具: & 和 >> 。
(1) &运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位。还可以判断奇偶:x&1=0,则x为偶,x&1=1则x为奇。
(2)>>运算比较单纯,相当于除以2n
快速幂的实现

1.定义函数f(a,b)=a的b次方
2.当b=1,f(a,b)=a
3.当b是偶数时,f(a,b)=f(a * a,b/2)
4.当b是奇数时,f(a,b)=f(a*a,b/2)*a

递归或迭代求解即可,时间复杂度O(log(b))

递归版代码

 LL Quick( LL a, LL b) {
    if( b == 1 ) return a;
   LL ans = Quick(a, b>>1);
       if( b&1 ) return ans * ans * a;
    else return ans * ans; }

迭代版代码:

LL quick( LL a, LL pow ) {
    LL ans = 1;
    while ( pow > 0 )
    {  if( pow&1 ) ans = ans * a;
       a = a * a;
      pow >>= 1;
     }
    return ans; }

3 例题:A的B次方

给定 n 组 ai,bi,pi,对于每组数据,求出 aibimod pi 的值。

输入格式 第一行包含整数 n。

接下来 n 行,每行包含三个整数 ai,bi,pi。

输出格式 对于每组数据,输出一个结果,表示 aibimod pi 的值。

每个结果占一行。

数据范围 1≤n≤100000, 1≤ai,bi,pi≤2×109
输入样例:
2
3 2 5
4 3 9
输出样例:
4
1

思路:裸的快速幂,中间取模即可
代码:
迭代版

#include<iostream>
using namespace std;

int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        long long  a,b,p,res=1;
        cin>>a>>b>>p;
        while(b)
        {
            if(b&1) res=res*a%p;
            b>>=1;//b右移了一位后,a也需要更新
            a=a*a%p;
        }
        cout<<res<<endl;

    }
}

递归版

#include<iostream>
using namespace std;
#define ull unsigned long long
ull quick_pow(ull a,ull b,ull p)
{
    if(b==0) return 1;
    a%=p;
    ull res=quick_pow(a,b>>1,p);
    if(b&1) return res*res%p*a%p;
    return res*res%p;
}
int main()
{
    int n;
    cin>>n;
    while(n--)
    {
        int a,b,p;
        cin.tie(0);
        ios::sync_with_stdio(false);
        cin>>a>>b>>p;
        cout<<quick_pow(a,b,p)<<endl;
    }
    return 0;
}


练习题目:
1、练习一

2、NOIP2013 转圈游戏

逆元

ax mod b=1的解x ,被称为模 b下 a的逆元,同时 a也是 x的逆元。逆元是个很有用的东西,在模运算中,a 的逆元x ,在运算中可以当多1/a 来用于计算。

“翠花,上酸菜”
1256 乘法逆元

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信奥教练Andy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值