前言
- 总结一些极其常用的模板,比赛前打印。
- 慢慢总结,不着急。
- 这里面还是只总结链接的好,因为博客会时常更新的,这样更新最源头的博客就ok了。
黑科技(杂项)
缺省源(主要是快读快输&俺不熟悉的组合数or逆元写法)
- 我的传送门:缺省源(没必要为了适应xcpc而用devc++)
暴力&DFS&BFS的艺术(学习总结全)
一些经典问题(问题列表)
- 传送门:一些经典问题
- 因为大多是直接copy的别人的代码,就不放出来了,设置【私密】hhh。
问题1:8数码问题(搜索&BFS&康托展开&双向BFS&Hash)
CF-简单AB题(思维&觉得有一点绕的题&或者是当时脑子短路了)
数论
数论基础(比较全的基础问题)
逆元
- 我的:逆元3种方法简述
莫比乌斯反演&整数分块
- 我的:莫比乌斯反演&整数分块
图论
链式前向星
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int M = 1e5 + 10;
int cnt, head[N]; // cnt初始化为0,head初始化为-1
//结构体
struct Edge {
int to, w, next;
Edge(int to = 0, int w = 0, int next = 0) : to(to), w(w), next(next) {
}
} edge[M];
//加边
void add(int u, int v, int w) {
edge[cnt] = Edge(v, w, head[u]), head[u] = cnt++; //正向边
edge[cnt] = Edge(u, w, head[v]), head[v] = cnt++;
//反向边(注意权值,按题目要求)
/* 建议全部从0开始,网络流那里从1开始好像就有问题cnt从1开始:edge[++cnt]=Edge(v,w,head[u]),head[u]=cnt;*/
}
//遍历:for(int i=head[u];~i;i=edge[i].next)
void init() {
memset(head, -1, sizeof(head)), cnt = 0; }
signed main() {
init();
return 0;
}
并查集
- 个人学习&总结:并查集学习&总结
最近公共祖先LCA
- 个人学习&总结:【最近公共祖先】学习&总结
数据结构
分块
- 我的传送门:分块学习&总结
线段树
- 我的传送门:线段树学习&总结
主席树
- 我的传送门:2021-07-09-主席树学习&总结
莫队
- 我的传送门:(2021.10.02)莫队学习&总结
字符串
- 我的传送门:字符串学习&总结(感觉主要是总结模板)
字符串HASH(牛逼克拉斯)
//首先得说明,模板都是"xyz"=x*B^2+y*B+z
//结构体方便双哈希
//哈希值不同子串一定不同,哈希值相同子串不一定相同。双哈希最保险
//#define int long long感觉是必须的,因为B=23,M=1e9+7,,,
struct HASH {
//不过好在HASH还是很快
int B; // B进制
int M; //大素数取余
int b[N]; // b[i]=b^i%M
int a[N]; //哈希前缀
void init(int n, int x, int y) {
b[0] = 1, B = x, M = y;
for (int i = 1; i <= n; i++) b[i] = b[i - 1] * B % M;
}
//核心操作:求子串哈希值
int get(int l, int r) {
return (a[r] - a[l - 1] * b[r - l + 1] % M + M) % M;
}
//#################以上是基础操作 ,以下随题目:::
} h[2];
可以解决的问题(HASH太强大了,所以还是贴一下)
前缀函数与kmp算法(我觉得应该称之为前缀函数算法)
模板:注意下标从0开始!从0开始!从0开始!
//在线算法:即,其实可以一个字符一个字符输入
struct KMP {
//与其说是KMP算法,不如说是前缀函数算法。而KMP也只是它的一个应用
int pi[N]; //前缀数组
//得到前缀函数,即前缀数组的值
//注意进入函数的是s还是s+1?
//当然是s,我发现,我之前就,从来没写过s+1的kmp。(之后多刷题,再说吧)
void get(char *s, int l) {
for (int i = 1; i < l; i++) {
int j = pi[i - 1];
while (j > 0 && s[i] != s[j]) j = pi[j - 1];
if (s[i] == s[j]) j++;
pi[i] = j;
}
}
//######################根据题目不同写不同的东西咯:
} kmp;
字典树Trie
基础操作:插入&查询
struct Trie {
// N大于可能出现的字符的总数
int ch[N][30], cnt;
int tag[N]; //给结尾打标记,表示这个字符串的数量
//插入字符串,注意这里下标从0开始
void insert(char *s, int l) {
int p = 0;
for (int i = 0; i < l; i++) {
int c = s[i] - 'a';
if (!ch[p][c]) ch[p][c] = ++cnt; //如果没有,就添加结点
p = ch[p][c];
}
tag[p]++; //一般赋值为1就ok了
}
//查找字符串
int query(char *s, int l) {
int p = 0;
for (int i = 0; i < l; i++) {
int c = s[i] - 'a';
if (!ch[p][c]) return 0;
p = ch[p][c];
}
return tag[p]; //返回个数,一般来说为1
}
//##################其他操作(依题而变):::::::::::
} trie;