算法基础课 (一) 基础算法

进制转换

#include<iostream>
using namespace std;
const int N = 100;
int n,m;
string s;
int x;//记录n进制转化成十进制;
int ans[N];
int main(){cin>>n>>s>>m;int t=1;for(int i=s.size()-1;i>=0;i--){if(s[i]<'A'){x += t*(int)(s[i]-'0');t *= n; }else{x += t*(int)(s[i]-'A'+10);t *= n;}}int st = 0;while(x){ans[st++] = (x%m);x /= m;}for(int i=st-1;i>=0;i--){if(ans[i]>=10)  printf("%c",(char)(ans[i]-10+'A'));else printf("%d",ans[i]);}  return 0;
}

quick_sort

void quick_sort(int q[], int l, int r)
{//递归的终止情况if (l >= r) return;//选取分界线。这里选数组中间那个数int i = l - 1, j = r + 1, x = q[l + r >> 1];//划分成左右两个部分while (i < j){do i ++ ; while (q[i] < x);do j -- ; while (q[j] > x);if (i < j) swap(q[i], q[j]);}//对左右部分排序quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

边界问题 :

因为边界问题只有这两种组合,不能随意搭配;

x不能取q[l]和q[l+r>>1];
quick_sort(q,l,i-1),quick_sort(q,i,r);x不能取q[r]和q[(l+r+1)>>1];
quick_sort(q,l,j),quick_sort(q,j+1,r);

merge_sort

void merge_sort(int q[], int l, int r)
{//递归的终止情况if (l >= r) return;//第一步:分成子问题int mid = l + r >> 1;//第二步:递归处理子问题merge_sort(q, l, mid);merge_sort(q, mid + 1, r);//第三步:合并子问题int k = 0, i = l, j = mid + 1;while (i <= mid && j <= r)if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];else tmp[k ++ ] = q[j ++ ];while (i <= mid) tmp[k ++ ] = q[i ++ ];while (j <= r) tmp[k ++ ] = q[j ++ ];//第四步:复制回原数组for (i = l, j = 0; i <= r; i ++, j ++ ) q[i]=tmp[j];
}

整数二分

  • 对于lower_bound : >= x的第一个元素的位置

  • 对于upper_bound : >x的第一个元素的位置

模板 :

bool check(int x) {/* ... */} // 检查x是否满足某种性质
​
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:
int bsearch_1(int l, int r){while (l < r){int mid = l + r >> 1;if (check(mid)) r = mid; // check()判断mid是否满足性质else l = mid + 1;//左加右减}return l;
}
​
// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int bsearch_2(int l, int r)
{while (l < r){int mid = l + r + 1 >> 1;//如果下方else后面是l则这里加1if (check(mid)) l = mid;else r = mid - 1;//左加右减}return l;
}
 

浮点数二分

bool check(double x) {/* ... */} // 检查x是否满足某种性质
​
double bsearch_3(double l, double r)
{const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求while (r - l > eps){double mid = (l + r) / 2;if (check(mid)) r = mid;else l = mid;}return l;
}

高精度加法

// C = A + B, A >= 0, B >= 0
vector<int> add(vector<int> &a,vector<int> &b){//c为答案vector<int> c;//t为进位int t=0;for(int i=0;i<a.size()||i<b.size();i++){//不超过a的范围添加a[i]if(i<a.size())t+=a[i];//不超过b的范围添加b[i]if(i<b.size())t+=b[i];//取当前位的答案c.push_back(t%10);//是否进位t/=10;}//如果t!=0的话向后添加1if(t)c.push_back(1);return c;
}

高精度减法


// C = A - B, 满足A >= B, A >= 0, B >= 0
vector<int> sub(vector<int> &A, vector<int> &B)
{//答案vector<int> C;//遍历最大的数for (int i = 0, t = 0; i < A.size(); i ++ ){//t为进位t = A[i] - t;//不超过B的范围t=A[i]-B[i]-t;if (i < B.size()) t -= B[i];//合二为一,取当前位的答案C.push_back((t + 10) % 10);//t<0则t=1if (t < 0) t = 1;//t>=0则t=0else t = 0;}//去除前导零while (C.size() > 1 && C.back() == 0) C.pop_back();return C;
}

高精度乘低精度

// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> &A, int b)
{//类似于高精度加法vector<int> C;//t为进位int t = 0;for (int i = 0; i < A.size() || t; i ++ ){//不超过A的范围t=t+A[i]*bif (i < A.size()) t += A[i] * b;//取当前位的答案C.push_back(t % 10);//进位t /= 10;}//去除前导零while (C.size() > 1 && C.back() == 0) C.pop_back();return C;
}

高精度乘高精度

char a1[10001], b1[10001];
int a[10001], b[10001], i, x, len, j, c[10001];
int main () {cin >> a1 >> b1; //不解释,不懂看前面int lena = strlen(a1); //每个部分都很清楚int lenb = strlen(b1); //这只是方便你们复制for (i = 1; i <= lena; i++)a[i] = a1[lena - i] - '0';//倒序存储for (i = 1; i <= lenb; i++)b[i] = b1[lenb - i] - '0';//倒序存储for (i = 1; i <= lenb; i++)for (j = 1; j <= lena; j++)c[i + j - 1] += a[j] * b[i];//存每位答案for (i = 1; i < lena + lenb; i++)if (c[i] > 9) {c[i + 1] += c[i] / 10;//进位c[i] %= 10;//取当前位答案}len = lena + lenb;while (c[len] == 0 && len > 1)//去除前导零len--;for (i = len; i >= 1; i--)//输出答案cout << c[i];return 0;
}

高精度除低精度

// A / b = C ... r, A >= 0, b > 0
vector<int> div(vector<int> &A, int b, int &r)//高精度A,低精度b,余数r
{vector<int> C;//答案r = 0;for (int i = A.size() - 1; i >= 0; i -- ){r = r * 10 + A[i];//补全r>=bC.push_back(r / b);//取当前位的答案r %= b;//r%b为下一次计算}reverse(C.begin(), C.end());//倒序为答案while (C.size() > 1 && C.back() == 0) C.pop_back();//去除前导零return C;
}

一维前缀和

前缀和能够快速计算一个序列的区间和,也有很多个问题里面不是直接用前缀和,但是借用了前缀和的思想;

预处理 : s[i] = a[i] + a[i-1]
求区间[l,r] : sum == s[r]-s[l-1]
“前缀和数组” 和 "原数组" 可以合二为一

应用 :

const int N=100010;
int a[N];
int main(){int n,m;scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=1;i<=n;i++) a[i]=a[i-1]+a[i];scanf("%d",&m);while(m--){int l,r;scanf("%d%d",&l,&r);printf("%d\n",a[r]-a[l-1]);}return 0;
}

二维前缀和

计算矩阵的前缀和:s[x][y] = s[x - 1][y] + s[x][y -1] - s[x-1][y-1] + a[x][y]
以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:
计算子矩阵的和:s = s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 -1]

应用 :

int s[1010][1010];
int n,m,q;
int main(){scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&s[i][j]);for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)s[i][j]+=s[i-1][j]+s[i][j-1]-s[i-1][j-1];while(q--){int x1,y1,x2,y2;scanf("%d%d%d%d",&x1,&y1,&x2,&y2);printf("%d\n",s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]);}return 0;
}

一维差分

差分是前缀和的逆运算,对于一个数组a,其差分数组b的每一项都是a[i]的前一项a[i-1]的差。

注意 : 差分数组和原数组必须分开存放!!!!!

给区间[l,r]中的每一个数加上c,B[l]+=c,B[r+1]-=c

应用 :

using namespace std;
int a[100010],s[100010];
int main(){int n,m;cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];for(int i=1;i<=n;i++) s[i]=a[i]-a[i-1];// 读入并计算差分数组while(m--){int l,r,c;cin>>l>>r>>c;s[l]+=c;s[r+1]-=c;// 在原数组中将区间[l, r]加上c}for(int i=1;i<=n;i++){s[i]+=s[i-1];cout<<s[i]<<' ';}// 给差分数组计算前缀和,就求出了原数组return 0;
}

二维差分

给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上c:
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c
const int N = 1e3 + 10;
int a[N][N], b[N][N];
void insert(int x1, int y1, int x2, int y2, int c)
{b[x1][y1] += c;b[x2 + 1][y1] -= c;b[x1][y2 + 1] -= c;b[x2 + 1][y2 + 1] += c;
}
int main()
{int n, m, q;cin >> n >> m >> q;for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)cin >> a[i][j];for (int i = 1; i <= n; i++)for (int j = 1; j <= m; j++)insert(i, j, i, j, a[i][j]); //构建差分数组while (q--){int x1, y1, x2, y2, c;cin >> x1 >> y1 >> x2 >> y2 >> c;insert(x1, y1, x2, y2, c);//加c}for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1]; //二维前缀和}}for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){printf("%d ", b[i][j]);}printf("\n");}return 0;
}

位运算

求n的第k位数字: n >> k & 1
返回n的最后一位1:lowbit(n) = n & -n

离散化

vector<int> alls; // 存储所有待离散化的值
sort(alls.begin(), alls.end()); // 将所有值排序
alls.erase(unique(alls.begin(), alls.end()), alls.end());   // 去掉重复元素
// 二分求出x对应的离散化的值int find(int x) // 找到第一个大于等于x的位置
{int l = 0, r = alls.size() - 1;while (l < r){int mid = l + r >> 1;if (alls[mid] >= x) r = mid;else l = mid + 1;}return r + 1; // 映射到1, 2, ...n
}

区间合并

题 : acwing803

// 将所有存在交集的区间合并
void merge(vector<PII> &segs)
{vector<PII> res;
​sort(segs.begin(), segs.end());
​int st = -2e9, ed = -2e9;for (auto seg : segs)if (ed < seg.first){if (st != -2e9) res.push_back({st, ed});st = seg.first, ed = seg.second;}else ed = max(ed, seg.second);
​if (st != -2e9) res.push_back({st, ed});
​segs = res;
}

快速加 :

LL qadd(LL a , LL b , int p){LL res = 0;while(b){if(b&1) res = (res + a) % p;a = (a + a) % p;b >>= 1;}return res;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/179440.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c语言和c++的const的区别

const C中的const&#xff1a; 1.const修饰的局部变量赋值常量时&#xff0c;局部变量保存在符号表中&#xff0c;修改不了&#xff0c;是一个常量 2.const修饰的全局变量保存在常量区&#xff0c;不能被修改 3.const修饰的全局变量默认是内部链接属性&#xff0c;加上extern就…

案例-某乎参数x-zse-96逆向补环境

文章目录 前言一、流程分析二、导出代码三、补环境总结 前言 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;不提供完整代码&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则…

springboot实现验证码功能

转载自 : www.javaman.cn 1、编写工具类生成4位随机数 该工具类主要生成从0-9&#xff0c;a-z&#xff0c;A-Z范围内产生的4位随机数 /*** 产生4位随机字符串*/public static String getCheckCode() {String base "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn…

Python使用http代理爬取dy视频播放量

现在在gpt的加持下写一些简单的代码还是很容易的&#xff0c;效率高&#xff0c;但是要有一点基础&#xff0c;不然有时候发现不了问题&#xff0c;这些都需要经验积累和实战&#xff0c;最好能和工作结合起来&#xff0c;不然很快一段时间就忘的干干净净了&#xff0c;下面就是…

异步爬虫提速实践-在Scrapy中使用Aiohttp/Trio

在构建爬虫系统时&#xff0c;提高爬虫速度是一个关键问题。而使用异步爬虫技术可以显著提升爬取效率。在本文中&#xff0c;我将与大家分享如何在Scrapy中利用Aiohttp或Trio库实现异步爬取&#xff0c;以加快爬虫的速度。让我们开始吧&#xff01; 1. 安装所需的库 首先&…

内存标记扩展(MTE):通过架构增强内存安全性

目录 一、简介 二、谷歌的声明 三、内存安全违规 四、MTE如何工作 五、大规模部署MTE

springboot实战之stream API应用过滤不符合条件的数据

现实项目&#xff0c;根据条件需要过滤列表中的数据。查询List<BgroupCartDto> cartList&#xff0c; orderTime不空的子集。 实现 List<BgroupCartDto> cartList ddBgroupCartMapper.selectList(wrapper); List<BgroupCartDto> result cartList.stream…

C语言——数组转换

将的两行三列数组转换为三行两列的数组 #define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h> int main() {int a[2][3]{{1,2,3},{4,5,6}};int b[3][2],i,j;for ( i 0; i <1; i){for ( j 0; j <2; j){printf("%5d",a[i][j]);b[j][i]a[i][j];}printf(&…

python tkinter 使用(七)

python tkinter 使用(七) 本篇文章主要讲下tkinter 中的message 控件. Message控件可以用于在窗口中显示一段文本消息. 以下是个简单的例子: #!/usr/bin/python3 # -*- coding: UTF-8 -*- """Author: zhTime 2023/11/24 上午11:38 .Email:Describe: "…

为第一个原生Spring5应用程序添加上Log4J日志框架!

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

【.NET全栈】.net的微软API接口与.NET框架源码

文章目录 0 前言1 微软官方.net接口学习2 .NET框架源码总结 0 前言 如果浏览器打不开链接&#xff0c;换一个浏览器打开。 我是 打不开微软的链接&#xff0c;使用&#xff1a; 可以打开&#xff01;&#xff01;&#xff01; 1 微软官方.net接口学习 https://docs.microsoft…

Golang Proxy服务:构建高性能的网络代理

Golang Proxy服务&#xff1a;构建高性能的网络代理 简介 在当今互联网时代&#xff0c;代理服务变得日益重要。它可以帮助用户访问被限制的内容&#xff0c;保护用户隐私&#xff0c;加速网络访问等。Golang是一种高性能的编程语言&#xff0c;它的并发特性和网络库使得它成…

如何写好产品软文?软文撰写指南!

针对某种产品写一篇软文&#xff0c;我们应该怎么构思&#xff0c;怎么提笔去写&#xff0c;怎么写得让用户认可我们的产品&#xff0c;并产生消费的冲动&#xff0c;这是需要讲究技巧的。 今天伯乐网络传媒来给大家分享三个步骤&#xff0c;教你轻轻松松撰写一篇爆文&#xf…

电子学会C/C++编程等级考试2022年03月(二级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:温度统计 现有一段时间的温度数据,请统计指定温度出现的次数。 时间限制:1000 内存限制:65536输入 第一行一个整数n,表示温度数据的个数。(0 < n ≤ 200) 第二行n个整数,以空格分隔,每个整数表示一个温度,温度的范围大…

Opencv-C++笔记 (19) : 分水岭图像分割

文章目录 一、基于距离变换与分水岭的图像分割1、图像分割2、距离和变换与分水岭距离变换常见算法有两种分水岭变换常见的算法 3、距离变换API函数接口4、watershed 分水岭函数API接口步骤 5、代码 一、基于距离变换与分水岭的图像分割 1、图像分割 图像分割(Image Segmentat…

LeetCode 每日一题 2023/11/20-2023/11/26

记录了初步解题思路 以及本地实现代码&#xff1b;并不一定为最优 也希望大家能一起探讨 一起进步 目录 11/20 53. 最大子数组和11/21 2216. 美化数组的最少删除数11/22 2304. 网格中的最小路径代价11/23 1410. HTML 实体解析器11/24 2824. 统计和小于目标的下标对数目11/25 14…

c++中using的声明

using的编译指令 using的编译指令使整个命名空间的标识符可用 #include<iostream> using namespace std; namespace namea { int a 10; void foo() { cout << "hello using" << endl; } } void test01(){ //int a 100;…

解密编程难题:程序员的突破之路

引言&#xff1a; 在编程的世界里&#xff0c;技术难题就像是一道道难以逾越的障碍&#xff0c;让程序员们倍感挑战。Bug、性能优化和跨平台兼容性等问题&#xff0c;常常困扰着开发者们。然而&#xff0c;正是这些难题激发了程序员们的求知欲和创造力&#xff0c;让他们不断寻…

职场“雷人”瞬间

职场是人际交往的舞台&#xff0c;而在这个舞台上&#xff0c;总会有一些令人哭笑不得的瞬间。领导的奇怪任务、同事的自以为是&#xff0c;抑或是技术一无所知的领导对任务的荒谬要求&#xff0c;这些故事让我们在工作中既有欢笑&#xff0c;又有无语。 1. 领导的“挥洒自如”…

Android问题记录 - Unable to make field private final java.lang.String java.io.File.path accessible(持续更新)

文章目录 前言开发环境问题描述问题分析解决方案补充内容最后 前言 最近一个Flutter项目有新需求&#xff0c;开发时一直是在iOS设备上运行&#xff0c;花了几天做完后运行到Android设备测试&#xff0c;结果项目构建失败了。 开发环境 Flutter: 3.7.11Android Studio: 2022…