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


 


推荐阅读
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 本题来自WC2014,题目编号为BZOJ3435、洛谷P3920和UOJ55。该问题描述了一棵不断生长的带权树及其节点上小精灵之间的友谊关系,要求实时计算每次新增节点后树上所有可能的朋友对数。 ... [详细]
  • JSOI2010 蔬菜庆典:树结构中的无限大权值问题
    本文探讨了 JSOI2010 的蔬菜庆典问题,主要关注如何处理非根非叶子节点的无限大权值情况。通过分析根节点及其子树的特性,提出了有效的解决方案,并详细解释了算法的实现过程。 ... [详细]
  • 2018-2019学年第六周《Java数据结构与算法》学习总结
    本文总结了2018-2019学年第六周在《Java数据结构与算法》课程中的学习内容,重点介绍了非线性数据结构——树的相关知识及其应用。 ... [详细]
  • 本文介绍如何利用栈数据结构在C++中判断字符串中的括号是否匹配。通过顺序栈和链栈两种方式实现,并详细解释了算法的核心思想和具体实现步骤。 ... [详细]
  • 本文介绍如何从字符串中移除大写、小写、特殊、数字和非数字字符,并提供了多种编程语言的实现示例。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 版本控制工具——Git常用操作(下)
    本文由云+社区发表作者:工程师小熊摘要:上一集我们一起入门学习了git的基本概念和git常用的操作,包括提交和同步代码、使用分支、出现代码冲突的解决办法、紧急保存现场和恢复 ... [详细]
  • JavaScript中的数组是数据集合的核心结构之一,内置了多种实用的方法。掌握这些方法不仅能提高开发效率,还能显著提升代码的质量和可读性。本文将详细介绍数组的创建方式及常见操作方法。 ... [详细]
  • 二叉树的链表实现
    本文介绍了一种使用链表结构表示二叉树的方法。通过定义节点结构和相关操作函数,可以方便地创建、插入和遍历二叉树。 ... [详细]
  • Python自动化测试入门:Selenium环境搭建
    本文详细介绍如何在Python环境中安装和配置Selenium,包括开发工具PyCharm的安装、Python环境的设置以及Selenium包的安装方法。此外,还提供了编写和运行第一个自动化测试脚本的步骤。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 探讨ChatGPT在法律和版权方面的潜在风险及影响,分析其作为内容创造工具的合法性和合规性。 ... [详细]
  • 本文将继续探讨前端开发中常见的算法问题,重点介绍如何将多维数组转换为一维数组以及验证字符串中的括号是否成对出现。通过多种实现方法的解析,帮助开发者更好地理解和掌握这些技巧。 ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
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社区 版权所有