算法模板(持续更新)
基础算法
高精度加法
1234567891011121314151617vector<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]; if (i < b.size()) t += b[i]; c.push_back(t % 10); t /= 10; } if (t) c.push_back(t); while (c.size() > 1 && !c.back()) c.pop_back(); return c;}
高精度减法
123456789101112131415161718192 ...
信阳师范大学算法工作室招新中~
你是否想在大学发现一个更精彩的新世界?
你是否对自己的天赋充满信心?(尤其是逻辑能力或数学思维)
你是否想体验最极致的编程乐趣?
你是否想找一群志同道合的朋友一起奋斗?
那么,来加入XYNU的算法工作室吧!
——————————————————————————————————
什么是ACM?
ACM 全称 ACM-ICPC,原本专指国际大学生程序设计竞赛(International Collegiate Programming Contest)。
由国际计算机学会(Association for Computing Machinery,简称 ACM )赞助与冠名。虽然从 2018 年起 ICPC 从 ACM 名下独立出来,但还是延续传统继续称之为 ACM 竞赛。
比赛赛制为 5 小时内三人一队利用一台计算机编程解决算法问题。其余类似赛制的比赛也常用 ACM 指代,泛指种种大学生算法竞赛。
进入工作室后能干什么?
我们关注的算法竞赛主要包括:
国际大学生程序设计竞赛(ICPC)
中国大学生程序设计竞赛(CCPC)
蓝桥杯程序设计竞赛
团体程序设计天梯赛
注:ICPC 和 CCPC ...
Educational Codeforces Round 171 (Rated for Div. 2) 题解
A. Perpendicular Segments
不难发现, \(A,B,C,D\) 可以当作正方形的四个顶点,\(len(AB)=len(CD)=\) 正方形对角线长度,因此只要在给定区间找到最大正方形即可。
code:
1234567891011121314151617181920212223242526272829303132333435#include <bits/stdc++.h>#define x first#define y second#define int long long#define endl '\n'using namespace std;typedef pair<int, int> PII;const int N = 200010;int T;int x, y, k;void solve(){ cin >> x >> y >> k; int d = min(x, y); cout << "0 0 " << ...
牛客周赛 Round 67 题解
A. 排序危机
签到
code:
12345678910111213141516171819202122#include <bits/stdc++.h>using namespace std;int n;string s, a, b, c;int main(){ cin >> n >> s; for (int i = 0; i < n; i++) { if (s[i] >= 'a' && s[i] <= 'z') a += s[i]; else if (s[i] >= '0' && s[i] <= '9') b += s[i]; else c += s[i]; } cout << a << b << c; return 0;}
B. 小 ...
牛客周赛 Round 66 题解
A. 小苯吃糖果
签到
code:
12345678910111213141516#include <bits/stdc++.h>using namespace std;int a[3];int main(){ cin >> a[0] >> a[1] >> a[2]; sort(a, a + 3); cout << max(a[0] + a[1], a[2]); return 0;}
B. 小苯的排列构造
构造一个 \(n\) 到 \(1\) 的排列即可
code:
1234567891011121314151617181920#include <bits/stdc++.h>using namespace std;int T;int n;int main(){ cin >> T; while (T--) { cin >> n; for (int ...
算法入门
语言基础
最适合竞赛的语言:\(C\)++
主要原因:
强大的标准库:\(C\)++ 提供了一个非常强大的标准模板库 \((STL)\),其中包括高效的数据结构(如 \(vector、map、set\) 等)和算法(如排序、搜索、二分查找等)。这些工具可以帮助参赛者快速实现复杂算法,减少编写底层代码的时间。
高效的执行速度:\(C\)++ 是一种编译型语言,其执行速度接近底层语言(如 \(C\) 和汇编),因此在执行时间上比解释型语言(如 \(Python\) 和 \(JavaScript\))有优势。对于很多竞赛题目,时间效率是关键,\(C\)++ 的高效性能使其特别适合处理大规模数据。
广泛的使用与支持:\(C\)++ 是绝大多数算法竞赛支持的主流语言,并且在竞赛社区中非常流行。大量的参考代码、学习资源和讨论也是用 \(C\)++ 实现的。
时空复杂度分析
在竞赛中,对于所有题目,都会限制程序的运行时间与空间。
因此,我们要对每道题进行时空复杂度分析。
时间复杂度:
时间复杂度衡量的是算法在输入规模 \(n\) 增加时,所需的操作次数增长的快慢。
\(C\)++ 每秒的运行速度 ...
Codeforces Round 982 (Div. 2) 题解
A. Rectangle Arrangement
要计算黑色区域的周长,可以把图形转化为矩形来计算。
code:
1234567891011121314151617181920212223242526272829303132333435363738#include <bits/stdc++.h>#define int long long#define x first#define y second#define endl '\n'using namespace std;const int N = 200010;int T;int n;int a[N];signed main(){ ios::sync_with_stdio(false); cin.tie(0), cout.tie(0); cin >> T; while (T--) { cin >> n; int x = 0, y = 0; while (n--) ...
c++读写优化
cin & cout
优点:不需要关注数据类型,使用方便。
缺点:速度比较慢,在面对大量数据时需要关闭同步流以加快速度。
关闭同步流
12ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);
sacnf & printf
优点:速度快。
缺点:写起来相对复杂。
快读 & 快写
以字符的形式进行读入和输出,速度快,使用简单。
快读
12345678910111213141516int read(){ int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') ...
异或线性基
异或线性基
对于一个数组 \(a\),若 \(p\) 是它的一组异或线性基,则
\(p\) 中任意非空子集异或和不为 \(0\)
\(p\) 中每个数的最高位 \(1\) 唯一
\(a\) 中任意元素都可以通过 \(p\) 的子集异或出来
构造方法
贪心法和高斯消元
由于高斯消元构造的异或线性基具有更好的性质,因此使用高斯消元法
例题
Luogu P3812 【模板】线性基
题目描述
给定 \(n\) 个整数(数字可能重复),求在这些数中选取任意个,使得它们的异或和最大。
输入格式
第一行一个数 \(n\),表示元素个数。
接下来一行 \(n\) 个数。
输出格式
仅一行,表示答案。
数据范围
\(1 \leq n \leq 50,\ 0 \leq S_i < 2^{50}\)
code:
123456789101112131415161718192021222324252627282930313233343536373839404142434445#include <bits/stdc++.h>using namespace std;typedef long ...
莫队
莫队
莫队主要用来快速处理一个数组中多个区间内不同数字的状态
核心思想
分块:把长度为 \(n\) 的数组分为 若干个 长度为\(\sqrt{n}\) 的块
离线:对于所有的查询,按照双关键字排序,同一块内按右端点从小到大,否则按块的先后顺序从左到右
定义两个指针 \(l, r\),代表当前维护的区间是 \([l,r]\),对于排好序的查询,用双指针依次扫描查询的区间,时间复杂度 \(O(n\sqrt{n})\)
复杂度分析
假设查询的数量也是 \(n\) * 对于 \(l\) 指针,假设每个块内的查询,\(l\) 都要从左到右或者从右到左,每次的距离是\(\sqrt{n}\),则一共需要跑 \(n\sqrt{n}\)
* 对于 \(r\) 指针,假设每当查询完一个块,\(r\) 指针都在 \(n\),并且要到当前块的最右边,则一共需要跑 \(n\sqrt{n}-\frac{(1+\sqrt{n})*\sqrt{n}}{2}\)
因此总时间复杂度为 \(O(n\sqrt{n})\)
常数优化
每个块内查询的右边界都是升序排序,导致相邻块过渡的时候,右边界相距过远
因此可以奇数块内 ...