关于快速幂和矩阵快速幂

2023-05-16

快速幂:可参考该链接百科快速幂也可以参考这个博客快速幂博客
给出快速幂的题目和代码:快速幂||取余计算
在这里插入图片描述

#include<iostream>
#include<string.h>
using namespace std;
typedef long long ll;
ll b, p, k;
int main(){
  cin>>b>>p>>k;
  ll c = b, d = p, m = k; 
  ll x = 1;
  while(p){
    if(p&1) x = x*b%k;
    b = (b * b)%k;
    p>>=1;
  }
  cout<<c<<"^"<<d<<" mod "<<m<<"="<<x%k<<endl;
  return 0;
}  

在有些题目中,当数据很大时,使用递归和递推复杂度很高,这时,使用矩阵快速幂就是一个很好的方法了。这里附上其他博主写的矩阵快速幂的知识矩阵快速幂
还有一题洛谷的矩阵快速幂题目:矩阵快速幂以及ac代码矩阵快速幂模板:

#include<iostream>
#include<string.h>
using namespace std; 
#define MOD 1000000007
typedef long long ll;
const ll maxn = 110;
ll n, k;
struct mat{
  ll m[maxn][maxn];
};
mat operator * (mat a, mat b){
  mat ret;
  memset(ret.m, 0, sizeof(ret.m));
  for(int i = 0; i < maxn; i++){
    for(int j = 0; j < maxn; j++){
      for(int k = 0; k < maxn; k++){
        ret.m[i][j] +=(a.m[i][k]%MOD)*(b.m[k][j]%MOD);
        ret.m[i][j]%= MOD;
      }
    }
  }
  return ret;
}
mat init_unit(){//构造单位矩阵 
  mat u;
  for(int i = 0; i < maxn; i++){
    u.m[i][i] = 1;
  }
  return u;
}
mat pow_mat(mat a, ll n){
  mat ret = init_unit();
  while(n){
    if(n&1) ret = ret*a;//n&1是判断n的二进制最后一位是不是1,是1返回1,不是则返回0 
    a = a*a; 
    n>>=1; 
  }
  return ret;
}
int main(){
  cin>>n>>k;
  mat a;
  for(int i = 0; i < n; i++){
    for(int j = 0; j < n; j++){
      cin>>a.m[i][j];
    }
  }
  mat res = pow_mat(a, k);
  for(int i = 0; i < n; i++){
    for(int j = 0; j < n; j++){
      cout<<res.m[i][j]<<" ";
    }
    cout<<endl;
  }
  return 0;
}

在矩阵快速幂有些题目中,最关键的是构造矩阵,构造矩阵先找到题目中的关系式,然后根据关系式右边的已知去构造矩阵,找到对应的关系
1.这里可以去参考每个小项的构造,找出规律,然后构造。这里想获得的是a[n], a[n-1],a[n-2]的矩阵,所以通过以下方式去构造,也可以通过关系式直接构造
2.还有一种矩阵构造的方法就是上面说的直接通过关系式去构造,附上其他博主的链接:矩阵构造方法
总之,在矩阵快速幂中,构造矩阵是很重要的。
以上博客参考了其他资料。

例如洛谷的一题:矩阵加速
在这里插入图片描述
这题中的等式右边只用到了a[x-3]和a[x-1],而没有用到a[x-2]; 通过做的几题可知,一般跳跃的使用,都会将被跳跃的信息补齐,(这里要将a[x-2]补齐)再去推出。这里已知a[1],a[2],a[3]所以可通过这三项去构造(a[x],a[x-1],a[x-2])(当然,不是每题所有的已知都要用上),通过a[x]=1a[x-1]+0a[x-2]+1a[x-3](这里将被跳跃的信息补齐了)可得a[x+1]=1a[x]+0a[x-1]+1a[x-2];
通过(a[x-1], a[x-2], a[x-3])为了得到 (a[x], a[x-1], a[x-2]) ,可求出一个矩阵,这个矩阵就是我们要的矩阵
在这里插入图片描述

#include<iostream>
#include<string.h>
#define Mod 1000000007
using namespace std;
typedef long long ll; 
struct mat{
  ll m[5][5];
};
mat init(){
  mat res;
  memset(res.m, 0, sizeof(res.m));
  for(int i = 0; i < 5; i++){
    res.m[i][i] = 1;//这里是构造单位矩阵,即对角线是1,其他地方都是0
  }
  return res;
}
mat operator * (mat a, mat b){
  mat ret;
  memset(ret.m, 0, sizeof(ret.m));
  for(int i = 0; i < 5; i++){
    for(int j = 0; j < 5; j++){
      for(int k = 0; k < 5; k++){
        ret.m[i][j] += (a.m[i][k]%Mod)*(b.m[k][j]%Mod);
        ret.m[i][j] %= Mod;
      }
    }
  }
  return ret;
}
mat mul_total(mat x, ll n){
  mat a = init();
  while(n){
    if(n & 1)  a = a*x;
    x = x * x;
    n >>= 1;
  }
  return a;
}
mat base, ss;
int main(){
  ll t, n;
  cin>>t;
  while(t--){
    cin>>n;
    memset(base.m, 0, sizeof(base.m));
    memset(ss.m, 0, sizeof(ss.m));
    base.m[0][0] = base.m[0][1] = base.m[1][2] = base.m[2][0] = 1;//这里是所求得的矩阵 
    ss.m[0][0] = ss.m[0][1] = ss.m[0][2] = 1;//这里是a[3], a[2], a[1]的初始矩阵 
    if(n <= 3) cout<<1<<endl;
    else{
      mat s = mul_total(base, n-3);//减多少是根据初始矩阵中最大的下标是多少 
      ss = ss * s;
      cout<<ss.m[0][0]<<endl;
    }
  }
  return 0;
}

这里加入fibonacci的题目:斐波那契数列以及ac代码

#include<iostream>
#include<string.h>
#include<stdio.h>
using namespace std;
#define Mod 10000
typedef long long ll;
struct mat{
  ll m[5][5];
};
mat init(){
  mat a;
  memset(a.m, 0, sizeof(a.m));
  for(int i = 0; i < 5; i++){
    a.m[i][i] = 1;
  }
  return a;
}
mat operator * (mat a, mat b){
  mat c;
  memset(c.m, 0, sizeof(c.m));
  for(int i = 0; i < 5; i++){
    for(int j = 0; j < 5; j++){
      for(int k = 0; k < 5; k++){//因为输出后四位数,则每次计算后四位就可以了 
        c.m[i][j] += (a.m[i][k]%Mod)*(b.m[k][j] % Mod);
        c.m[i][j] %= Mod; 
      }
    }
  }
  return c;
} 
mat mul(mat x, ll n){
  mat y = init();
  while(n){
    if(n&1) y = y*x;
    x = x*x;
    n>>=1;
  }
  return y;
} 
mat a, b;
int main(){
  ll n;
  while((cin>>n) && (n != -1)){
    memset(a.m, 0, sizeof(a.m));
    memset(b.m, 0, sizeof(b.m));
    a.m[0][0] = a.m[0][1] = a.m[1][0] = 1;
    a.m[1][1] = 0;
    b.m[0][0] = 1;
    b.m[0][1] = 0;
    if(n == 0){
      cout<<0<<endl;
    }else if(n == 1){
      cout<<1<<endl;
    }else{
      mat c = mul(a, n-1);
      b = b*c;
      cout<<b.m[0][0]<<endl;
    }
  }
  return 0;
}

矩阵快速幂中还会涉及二分求和,以下是二分求和的题目以及参考博客:矩阵快速幂及二分求和题目和二分幂求和参考博客、题解、题解博客

这里也有涉及^和&符号的二进制运算符的题目HDU 2276:这里参考了其他的博主的博客
博客一、参考代码博客
以下为题意:在这里插入图片描述方法为:在这里插入图片描述以及我的ac代码:

#include<iostream>
#include<string.h>
#include<string>
using namespace std;
struct mat{
  int m[110][110];
};
mat ss, b;
int m, len;
mat init(){
  mat res;
  memset(res.m, 0, sizeof(res.m));
  for(int i = 0; i < len; i++){
    res.m[i][i] = 1;
  }
  return res;
}
mat mul(mat a, mat b){
  mat res;
  for(int i = 0; i < len; i++){
    for(int j = 0; j < len; j++){
      res.m[i][j] = 0;
      for(int k = 0; k < len; k++){
        res.m[i][j] ^= (a.m[i][k] & b.m[k][j]);
      }
    }
  }
  return res;
}
mat pow(mat a, int n){
  mat res = init();
  while(n){
    if(n&1) res = mul(res, a);
    a = mul(a, a);
    n >>= 1;
  }
  return res;
}
int main(){
  string s;
  while(cin>>m>>s){
    len = s.length();
    memset(ss.m, 0, sizeof(ss.m));
    for(int i = 0; i < len; i++){//灯的矩阵,以列来储存 
      ss.m[i][0] = s[i] - '0';
    }
    memset(b.m, 0, sizeof(b.m));
    b.m[0][0] = b.m[0][len-1] = 1;//这里开始构造需要的矩阵 
    for(int i = 1; i < len; i++){//注意这里是行为单位 
      b.m[i][i-1] = b.m[i][i] = 1; 
    } 
    mat c = pow(b, m);
    c = mul(c, ss);//因为行为单位,所以这里是c在前,ss在后,遵从矩阵的乘法 
    for(int i = 0; i < len; i++){
      cout<<c.m[i][0];//最后这里输出的是列,最后的结果是列 
    }
    cout<<endl;
  } 
  return 0;
}

如果有错误,欢迎指出

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于快速幂和矩阵快速幂 的相关文章

随机推荐

  • Python报错File “「string」“, line 1, in 「module」 NameError: name ‘q‘ is not defined

    Python报错File line 1 in NameError name q is not defined 笔者运行环境 xff1a Python 2 7 17 print span class token punctuation spa
  • MATLAB的appdesigner背景图片设置

    MATLAB的appdesigner背景图片设置 工作环境 xff1a windows10 MATLAB2017a 转变MATLAB2019b 前面因为课程需要做了一个简单的MATLABapp xff0c 在进行app背景图片设置的时候 x
  • ros-话题节点消息控制rviz中机械臂Publish Joint_State with Python to RVIZ-ros回炉再强学习(6)

    ros 话题节点消息Publish Joint State with Python to RVIZ ros回炉再强学习 xff08 6 xff09 笔者工作环境 xff1a ubuntu16 04 ros kinect 代码下载地址 xff
  • opencv边缘检测运用sobel算子源代码方法

    opencv边缘检测运用sobel算子源代码方法 span class token function import span cv2 span class token function import span numpy as np spa
  • v-rep仿真之键盘控制机械臂末端移动

    v rep仿真之键盘控制机械臂末端移动 键盘控制机械臂末端移动原理为 xff0c 设置机械臂逆运动学target xff0c 机械臂末端跟随target运动 xff0c 然后通过改变target的值 xff0c 从而达到控制机械臂末端移动的
  • urx驱动ur3和onrobot rg2

    urx驱动ur3和onrobot rg2 注意 xff1a 非常重要的一点 xff0c urx是可以在Python2和Python3都支持的 xff0c 随着时间改变 xff0c 如果有的读者发现Python2中不能使用 xff0c 报错m
  • ros-melodic安装解决sudo rosdep init问题

    ros melodic安装解决sudo rosdep init问题 解决办法1 去网站查看raw githubusercontent com的真实IP span class token function sudo span span cla
  • 上电浪涌电流

    上电浪涌电流 电机启动或者停转都会形成浪涌电流 xff0c 例如启动的浪涌最大 xff0c 毕竟电机启动静态电阻非常小 xff0c 上电等同短路 xff0c 其电机为感性负载 xff0c 由较大的无功电流 xff0c 对电网造成波动非常大
  • 电机功率计算公式

    电机功率计算公式 电动机输入功率 单相电机为P 61 UI xff0c 三相电机P 61 UIcos0 8 输出功率 xff08 驱动功率 xff09 P 61 FV F为力 牛顿 V xff1a 速度 m S xff09 换算到电机则有
  • C++ 中 map 字典与 set 集合的使用

    在 C 43 43 中 xff0c map 是关联容器 的一种 xff0c 关联容器将值 与键 关联到一起 xff0c 并使用键来查找值 这与 python 中的字典 类型类似 xff0c 也是用来存储键 值对 xff08 key valu
  • win11 安装 WSL2 在非 C 盘及配置(图形界面+代理)

    WSL 安装及配置 直接安装 WSL2 在非 C 盘启用 WSL 功能前提条件设置默认安装 WSL2安装在非 C 盘 图形界面先决条件更新 WSL 以支持 GUI 配置 WSL2 使用 Windows 网络代理 直接安装 WSL2 在非 C
  • CVTE嵌入式实习生与秋招

    目录 前言一 实习笔试二 实习面试三 实习工作内容四 公司看法 前言 今年暑假去CVTE实习了一个多月最后经过转正答辩 xff0c 获得了offer xff0c 现就我的实习经历和对公司的一些认知分享一下 xff08 仅代表个人观点 xff
  • 视频编解码行业及发展方向简述

    目录 一 视频行业1 视频是一个方兴未艾的大产业2 视频行业潜在商机大 人才缺口大3 了解华为海思的HI3518E方案 二 海思方案项目用到的硬件平台介绍1 本专栏文章使用的开发板配置2 处理器为什么选HI3518E 三 本专栏文章规划和核
  • 全面认识海思SDK及嵌入式层开发(1)

    目录 一 全面认识和检测配套开发套装1 套装配件介绍2 检测开发板3 注意 二 视频设备开发的技术流1 视频从产生到被消费的整个流程2 视频行业的商业角度分段3 几个疑问点 一 全面认识和检测配套开发套装 购买方式 xff1a 淘宝搜索 g
  • 嵌入式linux开发环境搭建(VMware16.0.0+Ubuntu16.04.3_X64)

    目录 一 安装VMware1 VMware介绍2 安装VMware16 0 0 二 安装ubuntu16 04 3 LTS1 Ubuntu介绍2 下载安装包iso3 安装 四 新安装Ubuntu的基本设置1 开机和关机等2 虚拟机基本设置3
  • 全面认识海思SDK及嵌入式层开发(2)

    目录 一 HI3518E方案系统整体架构介绍1 硬件上2 软件上 二 海思SDK的整体介绍三 海思SDK包的学习和实验1 2篇相关文档2 SDK包复制到linux原生目录中并解压3 SDK包操作的脚本程序研究4 SDK中源码包部分的配置编译
  • 计算机视觉之相机模型

    目录 一 相机模型1 相机与图像2 坐标系3 世界坐标系到摄像机坐标系4 摄像机坐标系到图像物理坐标系5 图像物理坐标系到图像像素坐标系6 摄像机坐标系到图像像素坐标系7 世界坐标系到图像像素坐标系 二 镜头畸变1 相机成像原理2 镜头畸变
  • vscode安装插件失败,完美解决

    vscode安装插件一直失败 xff0c 解决方案如下 访问vscode插件官网https marketplace visualstudio com vscode xff0c 搜索你要的插件点击插件详情 Version History 下载
  • ROS的topic通信机制

    1 通信步骤如图 xff1a 2 步骤介绍 第 xff08 0 xff09 步 xff1a talker gt master 发布者talker向mater注册 xff1a 包括节点的信息 需要发布的话题名等 xff0c 然后节点管理器RO
  • 关于快速幂和矩阵快速幂

    快速幂 xff1a 可参考该链接百科快速幂也可以参考这个博客快速幂博客 给出快速幂的题目和代码 xff1a 快速幂 取余计算 include lt iostream gt include lt string h gt using names