首页 > 其他分享 >高精度/前缀和/差分

高精度/前缀和/差分

时间:2023-07-25 21:14:17浏览次数:29  
标签:前缀 高精度 int back 差分 vector push size

  • 高精度

    • 存储方式:

      • 整数的长度一般小于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];
        

标签:前缀,高精度,int,back,差分,vector,push,size
From: https://www.cnblogs.com/moilip/p/17581024.html

相关文章

  • 左神算法-基础06-前缀树&贪心算法
    左神算法-基础06-前缀树&贪心算法介绍前缀树何为前缀树?如何生成前缀树?例子:一个字符串类型的数组arr1,另一个字符串类型的数组arr2。arr2中有哪些字符,是arr1中出现的?请打印。arr2中有哪些字符,是作为arr1中某个字符串前缀出现的?请打印。arr2中有哪些字符,是作为arr1中某个......
  • 前缀统计
    前缀统计题目给定N个字符串S1,S2,…,SN,接下来进行M次询问,每次询问给定一个字符串T,求S1~Sn中有多少个字符串是T的前缀。并且全部由小写字母组成输入第一行:一个字符串T(长度小于1000)第二行:n(<=20000)接下来n行,每行一个字符串(长度小于T的长度)输出一个整数,表示有多少个字符串......
  • 560. 和为 K 的子数组(前缀和解决子串问题)
    给你一个整数数组nums和一个整数k,请你统计并返回该数组中和为k的连续子数组的个数。示例1:输入:nums=[1,1,1],k=2输出:2>思路每个元素对应一个“前缀和”遍历数组,根据当前“前缀和”,在map中寻找「与之相减==k」的历史前缀和当前“前缀和”与历史前缀和......
  • 差分数组
    差分数组的主要适用场景是频繁对原始数组的某个区间的元素进行增减。比如说,我给你输入一个数组 nums,然后又要求给区间 nums[2..6] 全部加1,再给 nums[3..9] 全部减3,再给 nums[0..4] 全部加2,再给...一通操作猛如虎,然后问你,最后 nums 数组的值是什么?常规的思路很容易,......
  • 差分
    差分是前缀和的逆运算一维数组$diff[i]$记录了$a[i]-a[i-1]$对于区间$[l,r]$同时加$w$$Diff[1]+=w$看一道例题:Code:#include<iostream>usingnamespacestd;constintN=1e7+10;intq[N],s[N];voidinsert(intl,intr,intc){ s[l]+=c; s[r+1]......
  • 前缀和
    在学完数组后常会遇见这样的题如B3612【深进1.例1】求区间和:有n个数,$a1,a2,a3.....an(ai<=105),m<=103$,$l$,$r$,求区间内的和;$n$个数:$2$$7$$9$$1$$3$$6$$5$$3$你会写出这样的代码:while(m--){ for(inti=起点;i<=终点;i++) sum+=a[i]; ...............抛开题......
  • 全局路由前缀配置
    1、新建RouteConventio.cs文件///<summary>///全局路由前缀配置///</summary>publicclassRouteConventio:IApplicationModelConvention{///<summary>///定义一个路由前缀变量///</summary>privatere......
  • 2-3 编写函数 htoi(s),把由十六进制数字组成的字符串(包含可选的前缀 0x 或 0X)转换为与
    ArchlinuxGCC13.1.1 202304292023-07-2219:48:23星期六 点击查看代码#include<stdio.h>#include<ctype.h>inthtoi(constchar*s);intmain(){chararr[4]="0x3A";intresult=htoi(arr);printf("%d\n",resu......
  • 关于高精度计算的研究(1)——高精度加、减运算(2023-07-21)
    1、引入在C++中,我们常会需要做加减乘除等等运算首先我们来熟悉一下c++的计算符号:+(加号)             -(减号、负号)                  *(乘号)                    /(除号......
  • jsp 超链接带系统前缀
    如: <a href="www.iteye.com">iteye</a> 网页生成后点击此超链接,始终有如http://localhost:8080的前缀,变成http://localhost:8080/www.iteye.com  解决:加上http://前缀   <a href="http://www.iteye.com">iteye</a> ......