热门标签 | 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;
}


 


推荐阅读
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 题目Link题目学习link1题目学习link2题目学习link3%%%受益匪浅!-----&# ... [详细]
  • C++实现经典排序算法
    本文详细介绍了七种经典的排序算法及其性能分析。每种算法的平均、最坏和最好情况的时间复杂度、辅助空间需求以及稳定性都被列出,帮助读者全面了解这些排序方法的特点。 ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • C++: 实现基于类的四面体体积计算
    本文介绍如何使用C++编程语言,通过定义类和方法来计算由四个三维坐标点构成的四面体体积。文中详细解释了四面体体积的数学公式,并提供了两种不同的实现方式。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • 本文探讨了如何在模运算下高效计算组合数C(n, m),并详细介绍了乘法逆元的应用。通过扩展欧几里得算法求解乘法逆元,从而实现除法取余的计算。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • Splay Tree 区间操作优化
    本文详细介绍了使用Splay Tree进行区间操作的实现方法,包括插入、删除、修改、翻转和求和等操作。通过这些操作,可以高效地处理动态序列问题,并且代码实现具有一定的挑战性,有助于编程能力的提升。 ... [详细]
  • 本文详细介绍了 Apache Jena 库中的 Txn.executeWrite 方法,通过多个实际代码示例展示了其在不同场景下的应用,帮助开发者更好地理解和使用该方法。 ... [详细]
  • 本文详细介绍了Java中的访问器(getter)和修改器(setter),探讨了它们在保护数据完整性、增强代码可维护性方面的重要作用。通过具体示例,展示了如何正确使用这些方法来控制类属性的访问和更新。 ... [详细]
  • 本实验主要探讨了二叉排序树(BST)的基本操作,包括创建、查找和删除节点。通过具体实例和代码实现,详细介绍了如何使用递归和非递归方法进行关键字查找,并展示了删除特定节点后的树结构变化。 ... [详细]
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社区 版权所有