高精度/前缀和/差分

这篇具有很好参考价值的文章主要介绍了高精度/前缀和/差分。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  • 高精度

    • 存储方式:

      • 整数的长度一般小于1e6
      • 大整数的每一位存储到数组里
      • 存储时低位在前,高位在后,方便进位
    • 高精度加法

      • 每一位相加Ai + Bi + t, t表示进位取值0/1,逢十进一
      • 模板:
        //存储方式
        string a, b;//a = "123456"
        vector<int> A, B;//A = [6,5,4,3,2,1]
        for(int i = a.size() - 1; i >= 0; ++ i) A.push_back(a[i] - '0');
        for(int i = b.size() - 1; i >= 0; ++ i) B.push_back(b[i] - '0');
        
        //加法
        vector<int> add(vector<int> &A, vector<int> &B){
        	vector<int> C;
        	int t = 0;
        	for(int i = 0; i < A.size() || i < B.size(); ++ i){
        		if(i < A.size()) t += A[i]; //t = A[i] + B[i];
        		if(i < B.size()) t += B[i];
        		C.push_back(t % 10);
        		t /= 10;
        	}
        	if(t) C.push_back(1);
        	return C;
        }
        //逆序输出
        for(int i = C.size() - 1; i >= 0; -- i) cout << C[i];
        
        
    • 高精度减法

      • 每一位相减Ai - Bi - t, t 表示借位取值0/1
      • 模板:
        //判断是否有A > B
        //注意不能直接用字符串比较a,b的大小
        bool cmp(vector<int> &A, vector<int> &B){
        	if(A.size() != B.size()) return A.size() > B.size();
        	for(int i = A.size() - 1; i >= 0; ++ i)
        		if(A[i] != B[i]) return A[i] > B[i];
        }
        
        //减法,要保证A > B
        vector<int> sub(vector<int> &A, vector<int> &B){
        	vector<int> C;
        	for(int i = 0, t = 0; i < A.size(); ++ i){
        		t = A[i] - t;
        		if(i < B.size()) t -= B[i]; //t = A[i] - B[i] - t
        		C.push_back((t + 10) % 10);
        		if(t < 0) t = 1;
        		else t = 0;
        	}
        	//删除前导零
        	while(C.size() > 1 && C.back() == 0) C.pop_back();
        }
        //输出
        if(cmp(A, B)){
        	auto C = sub(A, B);
        	for(int i = C.size() - 1; i >= 0; -- i) cout << C[i];
        }else if(a == b) cout << 0;
        }else{
        	auto C = sub(B, A); //交换位置
        	for(int i = C.size() - 1; i >= 0; -- i) cout << C[i];
        }
        
        
    • 高精度乘法

      • A * b ,b<=10000, len(A) <= 1e6 , 乘的时候将b看作整体,而不是一位一位的乘
      • 一般是很大的数乘上一个小的数
      • 模板:
        string a;
        int b;
        vector<int> A;
        for(int i = a.size() - 1; i >= 0; -- i) A.push_back(a[i] - '0');
        //乘法
        vector<int> mul(vector<int> &A, vector<int> &B){
        	vector<int> C;
        	for(int i = 0, t = 0; i < A.size() || t; ++ i){
        		if(i < A.size()) t += A[i] * b;
        		C.push_back(t % 10);
        		t /= 10;
        	}
        	while(C.size() > 1 && C.back() == 0) C.pop_back();//去前导零(b==0时)
        	return C;
        }
        
    • 高精度除法

      • 一般是高精度的整数除以一个低精度的整数
      • 除法可以正序存储,为了一致性,依然逆序存储
      • 模板:
        vector<int> div(vector<int> &A, int b, int &r){//r是余数,C存储商
        	vector<int> C;
        	r = 0;
        	for(int i = A.size() - 1; i >= 0; -- i){//从高位开始算
        		r = r * 10 + A[i];
        		C.push_back(r % b);
        		t /= b;
        	}
        	reverse(C.begin(), C.end());
        	while(C.size() > 1 && C.back() == 0) C.pop_back();
        	return C;
        }
        
        
        
  • 前缀和

    • 一维前缀和

      • Sn = a1 + a2 + a3 + a4 + ....+ an
      • Sn = Sn-1 + an
      • O(1) 求区间和
      • 前缀和思想很重要!!
      • 模板:

        //初始化
        for(int i = 1; i <= n; ++ i) s[i] = s[i - 1] + a[i];
        //求和
        cout << s[r] - s[l - 1];
        
    • 二维前缀和

      • 基于容斥原理
      • 模板:

        //初始化
        for(int i = 1; i <= n; ++ i)
        	for(int j = 1; j <= m; ++ j)
        		s[i][j] = s[i][j - 1] + s[i - 1][j] - s[i - 1][j - 1] + a[i][j];
        //区间求和 左上角(a, b) 右下角(c, d)
        cout << s[c][d] - s[a - 1][d] - s[c][b - 1] + s[a - 1][b - 1];
        
        
  • 差分

    • 差分与前缀和互为逆运算
    • O(1) 区间修改
    • 差分的前缀和即为原数组
    • 一维差分

      • 模板:

        void add(int l, int r, int c){ //在区间[l, r] 上加上c
        	b[l] += c;
        	b[r + 1] -= c;
        }
        //差分数组初始化,初始化就相当于在[i, i] 区间上加上a[i]
        //所以初始化就与区间修改操作统一了
        for(int i = 1; i <= n; ++ i) add(i, i, a[i]);
        
        //差分数组初始化
        for(int i = 1; i <= n; ++ i) b[i] = a[i] - a[i - 1];
        
        //求原数组,直接利用b数组
        for(int i = 1; i <= n; ++ i) b[i] += b[i - 1];
        
    • 二维差分

      • 模板:

        //在以(x1, y1)为右上角(x2, y2)为左上角的矩形区域加上c
        void add(int x1, int y1, int x2, int y2, int c){
        	d[x1][y1] += c;
        	d[x2 + 1][y1] -= c;
        	d[x1][y2 + 1] -= c;
        	d[x2 + 1][y2 + 1] += c;
        }
        //求原数组
        for(int i = 1; i <= n; ++ i)
        	for(int j = 1; j <= m; ++ j)
        		d[i][j] += d[i - 1][j] + d[i][j - 1] + d[i - 1][j - 1];
        

文章来源地址https://www.toymoban.com/news/detail-603076.html

到了这里,关于高精度/前缀和/差分的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++高精度算法

    目录 前言:  思路: 高精度加法: 高精度减法: 高精度乘法: 高精度除法:  代码: 一、高精度加法 二、高精度减法  三、高精度乘法  四、高精度除法 最后         计算机最初、也是最重要的应用就是数值运算。在编程进行数值运算时,有时会遇到运算的精度要求特

    2024年02月14日
    浏览(32)
  • 高精度加法

    高精度问题是指两个数字非常大,超过了 int ,甚至 long long 的范围,数字的位数甚至能达到 (10^5) ,那么如果要实现这样两个大数字的运算,需要解决以下两个问题: 如何存储? 这样的两个数字相加是不可能用普通类型来存储的,所以我们第一个要解决的问题就是如何存储

    2024年02月08日
    浏览(32)
  • 高精度除法

    高精度除法和乘法讨论的一样,都是一个大整数和一个小整数之间的运算。 算法思路 根据小学除法一样,我们还是模拟这个过程。 注意这里遍历 (A) 数组的时候要按照我们读数字的顺序,也就是从数组尾部到头部遍历。 每一位的计算过程应该是,上一轮的余数 (r) 乘 (

    2024年02月08日
    浏览(36)
  • C++高精度问题

    C++中int不能超过2^31-1,最长的long long也不能超过2^63-1,所以我们在题目中如果碰到了很长很长的数,并且需要进行大数运算时,就需要高精度存储。 由于int和long long的限制,我们要想存放很长的数就需要利用数组存储,C++中可以利用STL中的vector容器存储 读取:  由于数据很大,

    2024年01月24日
    浏览(43)
  • 高精度算法详解

    首先要知道为什么需要高精度算法: 高精度算法是 处理大数字 的数学计算方法,当数字过大不能用 int 和 long long 存储时,我们就可以 使用string和vector类型 来存储他们的每一位,然后进行计算。 我们可以先把要输入的两个数字放到vector中存储,注意要 反着存(后边做加法

    2024年01月17日
    浏览(40)
  • 【算法】模拟,高精度

      P1601 A+B Problem(高精) - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路就是模拟,值得注意的就是要用字符串类型输入。存进自己的int数组时要倒着存,因为如果是正着存的话,进位会有点trouble。 时间复杂度O(max(m,n))    P1303 A*B Problem - 洛谷 | 计算机科学教育新生态 (lu

    2024年02月09日
    浏览(36)
  • 高精度乘法

    高精度加减法讨论的是两个大整数之间的运算。 而这里高精度乘除法讨论的是一个大整数和一个小整数之间的关系。 算法思路: 还是模拟小学的乘法列竖式,只不过此时不太一样,原本的列竖式是一位一位的乘,这里需要改变一下思路。 这里直接把小整数当成一个数,所乘

    2024年02月08日
    浏览(34)
  • 高精度减法

    要实现两个高精度数的减法,和高精度加法一样都是模拟竖式计算的过程,主要就是解决以下两个问题。 谁大谁小? 由于这两个数字都很大,但是不知道谁更大,所以要先判断哪个数更大,思路如下: 判断这两个数谁的位数更大,位数更大的自然更大。 如果位数不相同,从

    2024年02月08日
    浏览(34)
  • 高精度加法(含代码)

    例如: 1111111111111+9, 列成 竖式 , 先算个位, 1 + 9 = 10 , 满 10 , 向十位进 1 。 接下来, 处理 进位 。 十位: 1+1=2 - 2 百位: 无进位, 直接照抄. 1 - 1 千位: 1 - 1 万位: ... ...: ... 最高位: 1 - 1 最终结果: 所以, 1111111111111+ 9 = 1111111111120 1111111111111+8888888888889, 这个算式变成了 高精度 + 高精度

    2024年02月06日
    浏览(29)
  • 高精度延时

    在使用STM32的时候可以使用SYSTICK来实现高精度延时。 I.MX6U没有SYSTICK定时器,但是有GPT定时器来实现高精度延时。 GPT定时器是一个32位向上定时器(也就是从0x00000000开始向上递增计数), GPT定时器也可以跟一个值进行比较,当计数器值和这个值相等的话就发生比较事件,产生

    2024年02月02日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包