快速幂优化高精度乘法

news/2024/12/21 13:45:19/文章来源:https://www.cnblogs.com/dianman/p/18620685

NOI 1.6 12

题目描述

题目给出的 \(n\) 最大可以取到 \(100\) ,即计算 \(2^{100}\) ,明显是超过 long long\(2^{63}-1\),所以需要使用高精度来计算幂次方的乘法

  • 简单的高精度,即每次计算一个小整数乘上一个大整数

循环 \(n\) 次,每次对上一次的积都乘以 \(2\)

vector<int> ans = { 1 };//注意,需要对ans的第一位进行赋初值为1
for (int i = 1; i <= n; i++)ans = highdouble(ans);

然后就是简单高精度乘法的模板

vector<int> highdouble(vector<int> x) {vector<int> res;//定义返回数组int t = 0;//进位变量for (int i = 0; i < x.size(); i++) {t += 2 * x[i];//计算乘2的积res.push_back(t % 10);//取尾数放入t /= 10;}while (t) {//如果进位t还有值,就继续放入res.push_back(t % 10);t /= 10;}return res;//返回答案
}

以上的代码仅只用于大整数乘一个小整数,不能完成对两个大整数求积的操作、

简单的高精度计算的时间复杂度大约在 \(O(n^2)\) ,我们也可以使用快速幂的办法将时间复杂度优化到更低

  • 快速幂高精度计算
vector<int> quickpower(int b) {//快速幂函数vector<int> res, a;//使用vector来存储数据res.push_back(1);//对res第一项继续预处理a.push_back(2);//放入底数2while (b)//快速幂模板{if (b & 1) res = highplus(res, a);//使用高精度乘法计算a = highplus(a, a);//高精度倍增计算因子b >>= 1;}return res;
}

这里的高精度乘法需要计算两个大整数的积,采用错位相乘法

vector<int> highplus(vector<int>& x, vector<int>& y) {vector<int> temp(x.size() + y.size() + 1, 0);for (int i = 0; i < x.size(); i++)for (int j = 0; j < y.size(); j++)temp[i + j] += x[i] * y[j];int t = 0;for (int i = 0; i < temp.size(); i++) {t += temp[i];temp[i] = t % 10;t /= 10;}while (t > 0) {temp.push_back(t % 10);t /= 10;}while (temp.size() > 1 && temp.back() == 0) temp.pop_back();return temp;
}

其中,将 temp 赋值一个最大长度,即两个因子的长度和加 \(1\) ,并赋初值都为 \(0\)

循环两层计算相应位置上的乘积 temp[i + j] += x[i] * y[j]原理这里不做赘述

最后处理进位的问题,遍历整个 temp 数组,对每一位都继续进位操作

 t += temp[i];temp[i] = t % 10;t /= 10;while (t > 0) {//如果进位t还有值,就继续放入temp.push_back(t % 10);t /= 10;}

temp 数组去除前导 \(0\) 后返回高精度乘法的结果


经过实测,朴素的高精度乘法在规定的 \(1s\) 内最多只能计算到 \(2^{11438}\),而采用快速幂则可以计算到 \(2^{2^{15-1}}=2^{32767}\)

是一种极大的优化方案,如果我们的底数更大的话,快速幂的优势会变得更大

完整AC代码:

朴素算法

#include <vector>
#include <iostream>
using namespace std;int n;
vector<int> ans = { 1 };vector<int> highdouble(vector<int> x) {vector<int> res;int t = 0;for (int i = 0; i < x.size(); i++) {t += 2 * x[i];res.push_back(t % 10);t /= 10;}while (t) {res.push_back(t % 10);t /= 10;}return res;
}int main()
{cin >> n;for (int i = 1; i <= n; i++)ans = highdouble(ans);for (int i = ans.size() - 1; i >= 0; i--) cout << ans[i];return 0;
}

快速幂

#include <vector>
#include <iostream>
using namespace std;int n;vector<int> highplus(vector<int>& x, vector<int>& y) {vector<int> temp(x.size() + y.size() + 1, 0);for (int i = 0; i < x.size(); i++)for (int j = 0; j < y.size(); j++)temp[i + j] += x[i] * y[j];int t = 0;for (int i = 0; i < temp.size(); i++) {t += temp[i];temp[i] = t%10;t /= 10;}while (t > 0) {temp.push_back(t % 10);t /= 10;}while (temp.size() > 1 && temp.back() == 0) temp.pop_back();return temp;
}vector<int> quickpower(int b) {vector<int> res, a;res.push_back(1);a.push_back(2);while (b){if (b & 1) res = highplus(res, a);a = highplus(a, a);b >>= 1;}return res;
}int main()
{cin >> n;auto ans = quickpower(n);for (int i = ans.size() - 1; i >= 0; i--) cout << ans[i];return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/856332.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Docker网络基础知识

Docker 网络是 Docker 容器之间以及容器与主机或其他网络资源之间通信的基础。Docker网络基础1.默认网络当你启动一个容器是,如果没有特别指定网络,它会自动连接到Docker的默认桥接网络(bridge network)。 这个默认的桥接网络通常被称为bridge,它允许容器之间通过IP地址相…

川土微代理商深圳|CA-IS3740,CA-IS3741,CA-IS3742高性能四通道数字隔离芯片

CA-IS3740,CA-IS3741,CA-IS3742产品特性 •信号传输速率:DCto150Mbps •宽电源电压范围:2.5Vto5.5V •宽温度范围:‐40Cto125C •无需启动初始化 •默认输出高电平和低电平选项 •优异的电磁抗扰度 •高CMTI:150kV/s(典型值) •低功耗,(典型值): ▪电流为1.5mA/通道(@5…

大学8086汇编debug——关于int3断点之后继续调试的方法

预先 在汇编中打入int 3,然后在debug中利用G,就可以一路运行到断点处。 正文 在断点上可以用U来查看上下代码的位置断点后运行 然后用-g=xxxx:xxxx可以运行到下一个断点,或是直接运行至结束 还可以用-t=xxxx:xxxx逐步运行 注意:xxxx:xxxx是int 3下一个命令的地址

sunny替换响应体

本文来自博客园,作者:__username,转载请注明原文链接:https://www.cnblogs.com/code3/p/18620658

AuthBy pg walkthrough Intermediate window

nmap └─# nmap -p- -A -sS 192.168.226.46 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-12-21 01:01 UTC Stats: 0:01:06 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan SYN Stealth Scan Timing: About 52.12% done; ETC: 01:04 (0:01:00 rem…

学期(2024-2025-1) 学号(20241420) 《计算机基础与程序设计》第十三周学习总结

学期(2024-2025-1) 学号(20241420) 《计算机基础与程序设计》第十三周学习总结 作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里 <作业要求的链接>(2024-2025-1计算机基础与程序设计第十三周作业)这个作业…

纪念 Jonathan Barzilai

我在读博期间研究了关于非线性优化算法中的Barzilai-Borwein(BB)步长。正如我的导师安老师所言:梯度下降法是优化算法的基石(只考虑一般可微的目标函数)。在该算法中,迭代点每次沿着当前的负梯度方向"走一步",一直迭代下去,逼近最优解(当然是局部的)。一个自然地…

省选数学专题

昌吉市传教士出金身难度升序排序(大概吧)。 [AGC016C] +/- Rectangle 签,虽然国集作业。 贪心是显然的,不说了,这里只考虑正数如何填。 如果\(H\times W-\left\lfloor\frac{H}{h}\right\rfloor\times h\times \left\lfloor\frac{W}{w}\right\rfloor\times w\le \left\lflo…

《DNK210使用指南 -CanMV版 V1.0》第四十五章 人脸识别实验

第四十五章 人脸识别实验 1)实验平台:正点原子DNK210开发板 2)章节摘自【正点原子】DNK210使用指南 - CanMV版 V1.0 3)购买链接:https://detail.tmall.com/item.htm?&id=782801398750 4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/k210/A…

【寒武纪mlu220模型移植】(一)目标检测YoLoV8

前言:目标检测可能是大家用的比较多的,先完善这一篇吧。yolov5的导出可以参考官方文档。并且博主比较懒,已经做过一遍的事情,不想验证第二遍,如果有步骤错误或者疏漏导致中间遇到了问题,可以先自己debug,流程大致就是这样的。 一、修改源码首先是拉取yolov8最新的源码,…

基于钜泉计量AD的电表应用专题推荐(ATT7053D、HT7136、HT7627S-E

关于电力仪表上应用专题介绍,钜泉电能计量、PA驱动、Flash存储HiTrend(钜泉)电能计量芯片 单相计量ADC:ATT7053D,ATT7053C,HT7017,HT7017C 三相计量ADC:HT7036、HT7038、ATT7022E、HT7136、HT7132、HT7032-L 单相计量SOC:HT5019、HT5017,HT5025、HT5029,HT5033,HT503…

AI视频抠图来了!还可以替换视频背景,附下载链接

虽然人工智能正在飞速发展中,图像处理技术也在不断升级,但视频背景去除一直都是图像处理任务中最具挑战性的难题之一 Clipper是一款专注于高精度图像分割的AI工具,用于图像和视频的背景去除,允许用户直接输出透明背景(自定义颜色)的视频文件,还提供用一张图片或者其它视…