热门标签 | 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的序列{ai},代表一系列树木的美学价值。任务是处理m个查询,每个查询提供三个参数l、r和P,目标是在所有满足l < l' ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 洛谷 P4009 汽车加油行驶问题 解析
    探讨了经典算法题目——汽车加油行驶问题,通过网络流和费用流的视角,深入解析了该问题的解决方案。本文将详细阐述如何利用最短路径算法解决这一问题,并提供详细的代码实现。 ... [详细]
  • importjava.io.*;importjava.util.*;publicclass五子棋游戏{staticintm1;staticintn1;staticfinalintS ... [详细]
  • c语言二元插值,二维线性插值c语言
    c语言二元插值,二维线性插值c语言 ... [详细]
  • Flutter 核心技术与混合开发模式深入解析
    本文深入探讨了 Flutter 的核心技术,特别是其混合开发模式,包括统一管理模式和三端分离模式,以及混合栈原理。通过对比不同模式的优缺点,帮助开发者选择最适合项目的混合开发策略。 ... [详细]
  • UVa 1579 - 套娃问题
    本题主要涉及动态规划(DP)的应用,通过计算将前i个套娃合并成多个套娃组所需的最小操作次数来解决问题。具体来说,f(i) 表示前i个套娃合并成多个套娃组所需的操作次数,其计算公式为 f(i) = min(f(j) + dp(j+1, i))。 ... [详细]
  • POJ2263是一个经典的图论问题,涉及寻找从起点到终点的最大载重路径。本文将详细介绍该问题的背景、解题思路及代码实现。 ... [详细]
  • 管理UINavigationController中的手势返回 - Managing Swipe Back Gestures in UINavigationController
    本文介绍了如何在一个简单的闪存卡片应用中实现平滑的手势返回功能,以增强用户体验。 ... [详细]
  • 本文详细介绍了如何在Windows操作系统中配置和使用Lex(Flex)与Yacc(Bison),包括软件的下载、安装以及通过示例验证其正确性的步骤。 ... [详细]
  • 在Qt框架中,信号与槽机制是一种独特的组件间通信方式。本文探讨了这一机制相较于传统的C风格回调函数所具有的优势,并分析了其潜在的不足之处。 ... [详细]
  • 本文介绍了如何在不同操作系统上安装Git,以及一些基本和高级的Git操作,包括项目初始化、文件状态检查、版本控制、分支管理、标签处理、版本回退等,并简要提及了开源许可协议的选择。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 编译原理中的语法分析方法探讨
    本文探讨了在编译原理课程中遇到的复杂文法问题,特别是当使用SLR(1)文法时遇到的多重规约与移进冲突。文章讨论了可能的解决策略,包括递归下降解析、运算符优先级解析等,并提供了相关示例。 ... [详细]
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社区 版权所有