热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

第2周:高精度计算(支持任意进制,仅需调整基数)+前缀和+差分技术

本周课程涵盖了高精度计算、前缀和及差分技术。在高精度计算部分,我们将探讨如何处理任意进制的数值运算,包括但不限于正数的加法、减法和乘法。通过调整基数,可以灵活应对不同进制的需求。前缀和与差分技术则主要用于高效解决数组和区间查询问题,提升算法性能。

一、高精度运算(都是正数)

1、高精度加法(大数+大数)

2、高精度减法(大数-大数)

3、高精度乘法(大数*小数)

4、高精度除法(大数/小数)

二、前缀和

1、一维前缀和

2、二维前缀和(求小矩阵的和)

三、差分

1、一维差分

2、二维差分



1、高精度加法

模板:

#include
#include
#include
using namespace std;
const int N=1e6+10;
vector add(vector &A,vector &B)
{int t=0;vector C;for(int i=0;i=1)C.push_back(t);return C;//返回的类型是vector的
}
int main()
{string a,b;vectorA,B;//A,B两个容器cin>>a>>b;for(int i&#61;a.size()-1;i>&#61;0;i--)//a.size()字符串的长度A.push_back(a[i]-&#39;0&#39;);//将字符串逆序存入,把值加到B的末尾for(int i&#61;b.size()-1;i>&#61;0;i--)B.push_back(b[i]-&#39;0&#39;);vector C&#61;add(A,B);int len&#61;C.size();//最后结果的长度for(int i&#61;len-1;i>&#61;0;i--)//逆序放入也要逆序输出cout<}

2、高精度减法

模板

#include
#include
#include
using namespace std;
//先比较输入的两个数的大小
bool cmp(string a,string b)
{if(a.length()!&#61;b.length())return a.length()>b.length();for(int i&#61;0;ib[i];}return 1;//两个值相等
}
vector sub(vector &A,vector &B)
{int t&#61;0;vector C;for(int i&#61;0;i&#61;0)t&#61;0;elset&#61;1;}//清除前导0while(C.size()>1&&C.back()&#61;&#61;0)//直到最后剩下一个数为0时就不能在删了C.pop_back();//把最后一个数删掉return C;
}
int main()
{string a,b;cin>>a>>b;vectorA,B;for(int i&#61;a.size()-1;i>&#61;0;i--)A.push_back(a[i]-&#39;0&#39;);for(int i&#61;b.size()-1;i>&#61;0;i--)B.push_back(b[i]-&#39;0&#39;);vector C;//判断A,B的大小&#xff0c;决定正负号if(cmp(a,b)){C&#61;sub(A,B);for(int i&#61;C.size()-1;i>&#61;0;i--)cout<&#61;0;i--)cout<}

3、高精度乘法&#xff08;大数*小数&#xff09;

&#xff08;1&#xff09;思路&#xff1a;这里是直接把较小的那个数当成一个整体来算的&#xff0c;妙&#xff01;&#xff01;&#xff01;

&#xff08;1&#xff09;模板

#include
#include
#include
using namespace std;
vector mul(vector &A,int b)
{int t&#61;0;vector C;for(int i&#61;0;i1&&C.back()&#61;&#61;0)//删除前导0C.pop_back();//把容器A中的最后一个删掉return C;
}
int main()
{string a;int b;vector A;cin>>a>>b;for(int i&#61;a.size()-1;i>&#61;0;i--)A.push_back(a[i]-&#39;0&#39;);vector C&#61;mul(A,b);for(int i&#61;C.size()-1;i>&#61;0;i--)cout<}

4.高精度除法

模板

#include
#include
#include
#include
using namespace std;
vector div(vector &A,int b,int &r)//r余数
{vector C;//这里要逆序计算&#xff0c;因为前面是逆序存放的&#xff0c;但是由于考虑//到加减乘除可能在一起混合使用的情况&#xff0c;为了避免输入的麻烦&#xff0c;就把除法也逆序输入了 。//但是除法我们本来就是顺着来的。for(int i&#61;A.size()-1;i>&#61;0;i--){r&#61;r*10&#43;A[i];C.push_back(r/b);//这里存放到c里的答案是顺序的r%&#61;b;}reverse(C.begin(),C.end());//虽然C已经是顺序排放了&#xff0c;但是输出的时候是逆序&#xff0c;所以//把C转置一下while(C.size()>1&&C.back()&#61;&#61;0)C.pop_back();return C;
}
int main()
{string a;int b;vector A;cin>>a>>b;for(int i&#61;a.size()-1;i>&#61;0;i--)A.push_back(a[i]-&#39;0&#39;);int r&#61;0;//一开始余数0vector C&#61;div(A,b,r);for(int i&#61;C.size()-1;i>&#61;0;i--)cout<}

二、前缀和

1、一维前缀和&#xff1a;公式&#xff0c;sum[i]&#61;sum[i-1]&#43;a[i];下标i从1开始取。

2.二维前缀和

思路&#xff1a;

题目&#xff1a;https://www.acwing.com/problem/content/798/(求子矩阵的和&#xff09;


#include
using namespace std;
const int M&#61;1010;
int a[M][M],sum[M][M];
int main()
{int n,m,q;scanf("%d%d%d",&n,&m,&q);for(int i&#61;1;i<&#61;n;i&#43;&#43;){for(int j&#61;1;j<&#61;m;j&#43;&#43;){scanf("%d",&a[i][j]);}}for(int i&#61;1;i<&#61;n;i&#43;&#43;){for(int j&#61;1;j<&#61;m;j&#43;&#43;){//前缀和;减去多出来的两个小正方形&#xff0c;在加上被多减去的小正方形sum[i][j]&#61;sum[i][j-1]&#43;sum[i-1][j]-sum[i-1][j-1]&#43;a[i][j];//矩阵前缀和}}while(q--){int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);//小矩阵的和&#61;sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]&#43;sum[x1-1][y1-1]printf("%d\n",sum[x2][y2]-sum[x2][y1-1]-sum[x1-1][y2]&#43;sum[x1-1][y1-1]);}return 0;
}

三&#xff0c;差分

1、一维差分

&#xff08;1&#xff09;思路&#xff1a;令B1&#61;A1,B2&#61;A2-A1,...Bn&#61;An-A(n-1),则An&#61;B1&#43;B2&#43;...&#43;Bn&#xff0c;称数组B为数组A的差分&#xff0c;数组A为数组B的前缀和。

作用&#xff1a;如果想要给数组A[l,r]里的每个数加上c,那么我们可以对b数组进行操作&#xff0c;只需要b[l]&#43;&#61;c&#xff08;可以使数组a从l往后的所有数加上c&#xff09;,b[r&#43;1]-&#61;c&#xff08;因为只需要给[l,r]里的数加上c&#xff0c;所以还要把r之后的数减去c&#xff09;,即可完成给数组a[l,r]里的每个数加上c。

题目&#xff1a;797. 差分 - AcWing题库

#include
using namespace std;
const int M&#61;100010;
int a[M],b[M];
void insert(int l,int r,int c)//构造差分数组
{//我们只需要给[l,r]里的数加上c,所以只需要在l这里加就可给后面的数也加上。b[l]&#43;&#61;c;b[r&#43;1]-&#61;c;
}
int main()
{int n,m;scanf("%d%d",&n,&m);for(int i&#61;1;i<&#61;n;i&#43;&#43;)scanf("%d",&a[i]);for(int i&#61;1;i<&#61;n;i&#43;&#43;)insert(i,i,a[i]);//这里构造差分数组时可看成在[i,i]里加上a[i]while(m--){int l,r,c;scanf("%d%d%d",&l,&r,&c);insert(l,r,c);}for(int i&#61;1;i<&#61;n;i&#43;&#43;)b[i]&#43;&#61;b[i-1];//求差分数组的前缀和for(int i&#61;1;i<&#61;n;i&#43;&#43;)printf("%d ",b[i]);//每个b[i]对应的是a[i]的值return 0;
}

2、二维差分

思路&#xff1a;它是先把原数组一一插入到差分数组b中&#xff0c;然后在差分数组上面进行修改&#xff0c;最后通过求差分数组的前缀和来得到原数组。差分数组的前缀和与原数组的下标是一一对应的。二维差分&#xff1a;使a[i][j]是数组b[i][j]的前缀和,即b[i][j]是a[i][j]的差分数组。所以可以通过修改一个b[i][j](还未求前缀和前的)的值就可以影响其后面所有的值。

题目&#xff1a;https://www.acwing.com/problem/content/800/

#include
using namespace std;
const int M&#61;1010;
int a[M][M],b[M][M];
void insert(int x1,int y1,int x2,int y2,int c)//构造二维差分
{b[x1][y1]&#43;&#61;c;b[x2&#43;1][y1]-&#61;c;b[x1][y2&#43;1]-&#61;c;b[x2&#43;1][y2&#43;1]&#43;&#61;c;
}
int main()
{int n,m,q;scanf("%d%d%d",&n,&m,&q);for(int i&#61;1;i<&#61;n;i&#43;&#43;){for(int j&#61;1;j<&#61;m;j&#43;&#43;){scanf("%d",&a[i][j]);insert(i,j,i,j,a[i][j]);}}while(q--){int x1,y1,x2,y2,c;scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&c);insert(x1,y1,x2,y2,c);//先插入数&#xff0c;把插入的数加到差分数组b里的某一个元素就行了}//最后再求前缀和for(int i&#61;1;i<&#61;n;i&#43;&#43;)for(int j&#61;1;j<&#61;m;j&#43;&#43;)b[i][j]&#43;&#61;b[i][j-1]&#43;b[i-1][j]-b[i-1][j-1];for(int i&#61;1;i<&#61;n;i&#43;&#43;){for(int j&#61;1;j<&#61;m;j&#43;&#43;){printf("%d ",b[i][j]);}printf("\n");}return 0;
}

题目&#xff1a;

1、https://codeforces.com/problemset/problem/1455/B

思路&#xff1a;可发现sum&#61;1&#43;2&#43;3&#43;4&#43;...&#43;k&#xff0c;当在第一步后退时sum-2,在第2步后退时,sum-3,于是可发现如果在其中的任意一步选择了后退总可以有sum-x(x>1)。所以只需要比较sum与n之间的关系即可。

#include
using namespace std;
int main()
{int t,n;cin>>t;while(t--){cin>>n;int sum&#61;0,k&#61;0;//k来记录走的第几步while(sum}

2、https://codeforces.com/problemset/problem/1541/B
题意&#xff1a;给定一个整数数组&#xff0c;找出满足下标i 思路&#xff1a;首先可发现i&#43;j的取值范围在[3,2*n-1],即a[i]*a[j]的范围为[3,2*n-1],所以找出在这个范围里的所有因子x,x即为a[i],于是可得a[j]。再判断a[i],a[j]是否是存在的且a[i]*a[j]&#61;&#61;i&#43;j,同时注意我们在找因子的时候会出现a[i]&#61;&#61;a[j]的情况&#xff0c;所以还要加上a[i]!&#61;a[j]这个条件&#xff08;题目要求&#xff09;。
这道题是先由乘积结果再来求出这两个数的&#xff0c;只要确定了其中一个数&#xff0c;那么另一个数也可确定。

#include
#include
#define M 200005
using namespace std;
int main()
{int t,n,a[M];scanf("%d",&t);while(t--){//memset(a,0,sizeof(a));for(int i&#61;0;i}


3、https://codeforces.com/problemset/problem/466/A
思路&#xff1a;比较m张票单独买的价钱a*m和一起买的价钱b的大小来决定是要分开买还是一起买&#xff0c;如果一起买较便宜的话就计算出能一起整买多少份m,然后再把剩余的不足m张票的来比较是单独买还是以m张的团购价格来买便宜&#xff08;一开始忽略了这一步&#xff09;。
 

#include
using namespace std;
int main()
{int n,m,a,b,sum;cin>>n>>m>>a>>b;if(m*a<&#61;b){sum&#61;n*a;}else{sum&#61;n/m*b&#43;(n%m*a>b?b:n%m*a);}cout<}

4、Problem - 363B - Codeforces

思路&#xff1a;用前缀和来记录每个点和它自身之前的所有高度之和,再遍历查找连续长度为k的最小长度&#xff0c;由sum[i]-sum[i-k]可得到在不同地方连续k个长度的总和&#xff0c;把最小长度的下标保存起来。

#include
using namespace std;
int sum[150005];
int main()
{int n,k,x;scanf("%d%d",&n,&k);for(int i&#61;1;i<&#61;n;i&#43;&#43;){cin>>x;sum[i]&#61;sum[i-1]&#43;x;}int min&#61;sum[k],index&#61;1;for(int i&#61;k&#43;1;i<&#61;n;i&#43;&#43;){if(min>sum[i]-sum[i-k]){min&#61;sum[i]-sum[i-k];index&#61;i-k&#43;1;}}printf("%d\n",index);return 0;
}


 


推荐阅读
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • Prim算法在处理稠密图时表现出色,尤其适用于边数远多于顶点数的情形。传统实现的时间复杂度为 \(O(n^2)\),但通过引入优先队列进行优化,可以在点数为 \(m\)、边数为 \(n\) 的情况下显著降低时间复杂度,提高算法效率。这种优化方法不仅能够加速最小生成树的构建过程,还能在大规模数据集上保持良好的性能表现。 ... [详细]
  • 开发笔记:STL 容器 deque 的元素访问与迭代器详解
    开发笔记:STL 容器 deque 的元素访问与迭代器详解 ... [详细]
  • 计算 n 叉树中各节点子树的叶节点数量分析 ... [详细]
  • BZOJ4240 Gym 102082G:贪心算法与树状数组的综合应用
    BZOJ4240 Gym 102082G 题目 "有趣的家庭菜园" 结合了贪心算法和树状数组的应用,旨在解决在有限时间和内存限制下高效处理复杂数据结构的问题。通过巧妙地运用贪心策略和树状数组,该题目能够在 10 秒的时间限制和 256MB 的内存限制内,有效处理大量输入数据,实现高性能的解决方案。提交次数为 756 次,成功解决次数为 349 次,体现了该题目的挑战性和实际应用价值。 ... [详细]
  • 结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法
    结语 | 《探索二进制世界:软件安全与逆向分析》读书笔记:深入理解二进制代码的逆向工程方法 ... [详细]
  • 题目《UVa 11978 福岛核爆问题》涉及圆与多边形交集面积的计算及二分法的应用。该问题的核心在于通过精确的几何运算与高效的算法实现来解决复杂图形的面积计算。在实现过程中,特别需要注意的是对多边形顶点的平移处理,确保所有顶点包括最后一个顶点 \( p[n] \) 都经过正确的位移,以避免因细节疏忽导致的错误。此外,使用循环次数为50次的二分法能够有效提高算法的精度和稳定性。 ... [详细]
  • 在处理UVA11987问题时,关键在于实现并查集结构以支持删除操作。特别地,当需要删除某个节点时,如果该节点不是根节点,则处理相对简单;然而,若删除的是根节点,则需要进行额外的处理来维护集合的连通性。本文将详细介绍如何通过优化并查集算法,确保在删除根节点时仍能高效地维护数据结构的完整性和查询效率。 ... [详细]
  • [TyvjP1050] 动态规划求解最长公共子序列问题
    在解决最长公共子序列问题时,动态规划是一种高效的方法。具体而言,我们使用二维数组 `dp[i][j]` 来表示第一个字符串匹配到第 `i` 位,第二个字符串匹配到第 `j` 位时的最长公共子序列长度。状态转移方程为:当两个字符相等时,`dp[i][j] = dp[i-1][j-1] + 1`;否则,`dp[i][j] = max(dp[i-1][j], dp[i][j-1])`。通过这种方法,我们可以有效地计算出两个字符串的最长公共子序列。 ... [详细]
  • 本文详细探讨了Java集合框架的使用方法及其性能特点。首先,通过关系图展示了集合接口之间的层次结构,如`Collection`接口作为对象集合的基础,其下分为`List`、`Set`和`Queue`等子接口。其中,`List`接口支持按插入顺序保存元素且允许重复,而`Set`接口则确保元素唯一性。此外,文章还深入分析了不同集合类在实际应用中的性能表现,为开发者选择合适的集合类型提供了参考依据。 ... [详细]
  • 本文作为“实现简易版Spring系列”的第五篇,继前文深入探讨了Spring框架的核心技术之一——控制反转(IoC)之后,将重点转向另一个关键技术——面向切面编程(AOP)。对于使用Spring框架进行开发的开发者来说,AOP是一个不可或缺的概念。了解AOP的背景及其基本原理,对于掌握这一技术至关重要。本文将通过具体示例,详细解析AOP的实现机制,帮助读者更好地理解和应用这一技术。 ... [详细]
  • C++ 进阶:类的内存布局与虚函数类的实现细节
    C++ 进阶:类的内存布局与虚函数类的实现细节 ... [详细]
  • 本文详细介绍了如何在Linux系统中搭建51单片机的开发与编程环境,重点讲解了使用Makefile进行项目管理的方法。首先,文章指导读者安装SDCC(Small Device C Compiler),这是一个专为小型设备设计的C语言编译器,适合用于51单片机的开发。随后,通过具体的实例演示了如何配置Makefile文件,以实现代码的自动化编译与链接过程,从而提高开发效率。此外,还提供了常见问题的解决方案及优化建议,帮助开发者快速上手并解决实际开发中可能遇到的技术难题。 ... [详细]
  • CCCCGPLT L2005: 集合相似度计算的双指针算法优化 ... [详细]
  • MongoDB Aggregates.group() 方法详解与编程实例 ... [详细]
author-avatar
老鼠扛着刀找猫_592
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有