当前位置: 首页 > news >正文

NO.67十六届蓝桥杯备战|基础算法-倍增思想|快速幂|快速乘法(C++)

倍增,顾名思义就是翻倍。它能够使线性的处理转化为对数级的处理,极⼤地优化时间复杂度

P1226 【模板】快速幂 - 洛谷

利⽤「⼆进制」以及「倍增」的思想,通过⼀个具体的例⼦说明,⽐如 3 11 3^{11} 311

  • 幂运算的运算法则: a b + c = a b × a c a^{b+c}=a^{b} \times a^{c} ab+c=ab×ac
  • 通过⼀个数的⼆进制表⽰,可以写成若⼲数相加
    11 = ( 1011 ) 2 = 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 1 × 2 0 11=(1011)_{2}=1 \times 2^{3} +0 \times 2^{2} + 1 \times 2^{1}+1 \times 2^{0} 11=(1011)2=1×23+0×22+1×21+1×20
  • 两者结合:
    3 11 = 3 ( 1011 ) 2 = 3 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 1 × 2 0 = 3 8 × 3 0 × 3 2 × 3 1 3^{11}=3^{(1011)_{2}}=3^{1\times 2^{3}+0 \times 2^{2} + 1 \times 2^{1}+1 \times 2^{0}}=3^{8}\times3^{0} \times 3^{2} \times 3^{1} 311=3(1011)2=31×23+0×22+1×21+1×20=38×30×32×31

如何快速算出 3 1 , 3 2 . . 3 log ⁡ 2 n 3^{1}, 3^{2} .. 3^{\log_{2}n} 31,32..3log2n
其实很简单,从前往后看,后⼀个数是前⼀个数的平⽅
3 1 = 3 3^{1} = 3 31=3
3 2 = 3 1 × 3 1 = 9 3^{2}=3^{1} \times 3^{1} = 9 32=31×31=9
3 4 = 3 2 × 3 2 = 81 3^{4}=3^{2} \times 3^{2} = 81 34=32×32=81
3 8 = 3 4 × 3 4 = 6561 3^{8}=3^{4} \times 3^{4} = 6561 38=34×34=6561
只需将11的⼆进制表⽰中1 所对应的幂乘起来即可

如何实现这个算法,以 a b a^{b} ab为例

  • ⼀边提取b 的⼆进制表⽰中的每⼀位
  • ⼀边让a = a ∗ a ,不断变成之前的平⽅(倍增的思想)
  • 在提取b 的⼆进制表⽰时,如果这⼀位是1 ,就乘上对应位置的权值

取模运算的规则:

  1. 在计算过程中,只有加法和乘法时,如果最后要对整个结果取模,取模可以放在任意的位置
  2. 在计算过程中,存在减法时,结果可能出现负数,此时如果需要补正,就需要模加模的技巧来补正
  3. 在计算过程中,存在除法的时候,过程中取模是会出现错误的,需要求逆元
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
LL a, b, p;

LL qpow(LL a, LL b, LL p)
{
    LL ret = 1;
    while (b)
    {
        if (b & 1) ret = ret * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ret;
}

int main()
{
    cin >> a >> b >> p;

    printf("%lld^%lld mod %lld=%lld", a, b, p, qpow(a, b, p));
    
    return 0;
}
P10446 64位整数乘法 - 洛谷

跟「快速幂」的思想⼀致,我们通过⼀个具体的例⼦模拟⼀下算法的流程,⽐如3 × 11

  • 乘法的分配率: a × ( b + c ) = a × b + a × c a × (b + c) = a × b + a × c a×(b+c)=a×b+a×c
  • 通过⼀个数的⼆进制表⽰,可以写成若⼲数相加
    11 = ( 1011 ) 2 = 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 1 × 2 0 11 = (1011)_{2}=1 × 2^{3}+ 0 × 2^{2} +1 × 2^{1}+1×2^{0} 11=(1011)2=1×23+0×22+1×21+1×20
  • 两者结合:
    3 × 11 = 3 × ( 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 1 × 2 0 ) = 3 × 8 + 3 × 0 + 3 × 2 + 3 × 1 3 × 11=3× (1 × 2^{3}+ 0 × 2^{2} +1 × 2^{1}+1×2^{0})=3 × 8+3×0+3×2+3×1 3×11=3×(1×23+0×22+1×21+1×20)=3×8+3×0+3×2+3×1

如何实现这个算法呢,以a × b 为例

  • ⼀边提取b 的⼆进制表⽰中的每⼀位;
  • ⼀边让a = a + a ,不断变成之前的两倍(倍增的思想);
  • 在提取b 的⼆进制表⽰时,如果这⼀位是1 ,就加上对应位置的权值
#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
LL a, b, p;

LL qmul(LL a, LL b, LL p)
{
    LL sum = 0;
    while (b)
    {
        if (b & 1) sum = (sum + a) % p;
        a = (a + a) % p;
        b >>= 1;        
    }
    return sum;
}

int main()
{
    cin >> a >> b >> p;

    cout << qmul(a, b, p) << endl;
    
    return 0;
}

相关文章:

  • nacos的地址应该配置在项目的哪个文件中
  • 【网安】处理项目中的一些常见漏洞bug(java相关)
  • 换脸视频FaceFusion3.1.0-附整合包
  • Lua语言的边缘计算
  • 蓝桥杯 web 展开你的扇子(css3)
  • Linux : 内核中的信号捕捉
  • 15分钟完成Odoo18.0安装与基本配置
  • OpenSceneGraph 中的 LOD详解
  • USB3.0走线注意事项和其中的协议
  • 音视频学习(三十二):VP8和VP9
  • MCP项目开发-一个简单的RAG示例
  • 第15届蓝桥杯java-c组省赛真题
  • 其他 vector 操作详解(四十)
  • 如何做到一个项目的高可用保障
  • 美国mlb与韩国mlb的关系·棒球9号位
  • 第五章 定积分 第二节 微积分基本公式
  • k8s1.24升级1.28
  • OCC Shape 操作
  • 【CSS基础】- 02(emmet语法、复合选择器、显示模式、背景标签)
  • 基于大模型的脑梗死全流程诊疗技术方案
  • 做离心开关的企业的网站/重庆网站制作公司
  • Wordpress企业主题XShuan/seo做得比较好的企业案例
  • 做网站文案/怎样建网站?
  • 网站开发预算成本价/免费引流推广的方法
  • 网站建设费会计科目/58同城关键词怎么优化
  • 做团购网站商品从哪里找/小江seo