蓝桥杯软件赛Java研究生组/A组)第二章基础算法-第三节:倍增 ...

打印 上一主题 下一主题

主题 594|帖子 594|积分 1782

一:概述

倍增算法:是一种优化算法,通常应用在某些必要高效盘算指数幂的场景。它基于分治的头脑,通过反复求平方来实现快速盘算指数幂的目的。通常应用在最近公共祖先问题、二分查找等等
二:典型标题

(1)标题一(快速幂)

倍增算法最经典的应用就是快速幂,快速幂算法是一种高效盘算大整数幂的方法。如下快速幂盘算                                                   a                               b                                            a^{b}                     ab


  • 当                                             b                                      b                        b为偶数时
                                                    a                               b                                      =                                       a                                           b                                  2                                                 ∗                                       a                                           b                                  2                                                 =                            (                                       a                               2                                                 )                                           b                                  2                                                       a^{b} = a^{\frac{b}{2}}* a^{\frac{b}{2}}=(a^{2})^{\frac{b}{2}}                     ab=a2b​∗a2b​=(a2)2b​


  • **当                                        b                                  b                     b为奇数时
                                                    a                               b                                      =                            a                            ∗                                       a                                           b                                  2                                                 ∗                                       a                                           b                                  2                                                 =                            a                            ∗                            (                                       a                               2                                                 )                                           b                                  2                                                       a^{b} = a*a^{\frac{b}{2}}* a^{\frac{b}{2}}=a*(a^{2})^{\frac{b}{2}}                     ab=a∗a2b​∗a2b​=a∗(a2)2b​
**                                             b                            2                                       \frac{b}{2}                  2b​向下取整,迭代求解,直到                                   b                              b                  b为0为止
  1. public static long qmi(long a, long b, long p) {
  2.     long res = 1;  // 初始化结果为 1
  3.     while (b > 0) {  // 当指数 b 大于 0 时执行循环
  4.         if (b & 1 == 1) {  // 判断指数 b 的最低位是否为 1
  5.             res = res * a % p;  // 如果最低位为 1,则将底数 a 的当前幂乘到结果中,并取模 p
  6.         }
  7.         a = a * a % p;  // 底数 a 自乘,相当于计算 a^2, a^4, a^8, ...
  8.         b >>= 1;  // 将指数 b 右移一位,相当于将指数减半
  9.     }
  10.     return res;  // 返回结果
  11. }
复制代码
例如盘算                                                   2                               13                                            2^{13}                     213


  •                                               r                               e                               s                               =                               2                               ,                               a                               =                                           2                                  2                                          ,                               b                               =                               6                                      res=2,a=2^{2},b=6                        res=2,a=22,b=6
  •                                               r                               e                               s                               =                               2                               ,                               a                               =                                           2                                  4                                          ,                               b                               =                               3                                      res=2,a=2^{4},b=3                        res=2,a=24,b=3
  •                                                   r                                  e                                  s                                  =                                               2                                     5                                              ,                                  a                                  =                                               2                                     8                                              ,                                  b                                  =                                  1                                          res=2^{5},a=2^{8},b=1                           res=25,a=28,b=1
  •                                               r                               e                               s                               =                                           2                                  13                                          ,                               a                               =                                           2                                  16                                          ,                               b                               =                               0                                      res=2^{13},a=2^{16},b=0                        res=213,a=216,b=0
  • 倍增一般会和其他算法结合使用
(2)标题二(ST表求区间最值)

   

  思路:见ST表第二节:ST表
  1. int[] arr; // 给定的array
  2. int n = arr.length;
  3. // 预处理log数组,log[i]表示不大于i的最大二进制幂的指数
  4. int[] log = new int[n+1];
  5. log[1] = 0;
  6. for(int i = 2; i <= n; i++) {
  7. log[i] = log[i/2] + 1;
  8. }
  9. // 初始化ST表,st[i][j]表示从位置i开始,长度为2^J的区间的最值
  10. int[][] st = new int[n][log[n]+1];
  11. for(int i = 0; i < n; i++) {
  12. st[i][0] = arr[i]; // 长度为1的区间的最值就是其本身
  13. }
  14. // 动态规划填表
  15. for(int j = 1; j <= log[n]; j++) {
  16. for(int i = 0; i + (1<<j) <=n; i++) {
  17. st[i][j] = Math.max(st[i][j-1], st[i+(1<<(j-1))][j-1]);
  18. }
  19. }
  20. // 查找区间[L,R]的最值
  21. int k = log[R-L+1];
  22. // 这两个区间为:[L, L+2^k-1]和[R-2^K+1,R]
  23. return Math.max(st[L, k], st[R-(1<<j)+1][k])
复制代码
(3)标题三(最近公共祖先)



  1. void dfs(int x, int u) {
  2.     dep[x] = dep[u] + 1;// 设置当前节点的深度
  3.     father[x][0] = u; // 直接父节点
  4.     // 倍增法处理向上父节点
  5.     for(int i = 1; i <= 20; i++) {
  6.         father[x][i] = father[father[x][i-1]][i-1];
  7.     }
  8.     // 递归
  9.     for(int y: list[x]) {
  10.         if (y != u)
  11.             dfs(y, x)
  12.     }
  13. }
  14. int lca(int x, int y) {
  15.     // 确保x是更深的节点
  16.     if (dep[x] < dep[y]) {
  17.         swap(x, y);
  18.     }
  19.     // x向上跳,使x和y在同一深度
  20.     for(int i = 20; i >= 0; i--) {
  21.         if(dep[father[x][i]]>=dep[y]) {
  22.             x = father[x][i];
  23.         }
  24.     }
  25.     // 如果x和y相等,则找到了lca
  26.     if (x == y)
  27.         return x;
  28.     // 否则,同时开始向上跳,寻找
  29.     for(int i = 20; i >= 0; i--) {
  30.         if(father[x][i] != father[y][i]) {
  31.             x = father[x][i];
  32.             y = father[y][i];
  33.         }
  34.     }
  35.     // 返回
  36.     return father[x][0];
  37. }
  38. int n; // 节点数量
  39. List<Integer>[] list = new List[n+1]; // 邻接表
  40. for(int i = 0; i <= n; i++) {
  41.     list[i] = new ArrayList<>();
  42. }
  43. int[] dep = new int[n+1]; // 每个节点的深度
  44. int[][] father = new int[n+1][21]; // 倍增法,father[x][i]存储x的2^i父节点
  45. // 深度搜索,初始化dep数组和father数组
  46. dfs(1, 0);
  47. // 求解x和y的lca
  48. lca(x, y)
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

自由的羽毛

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表