1.数学
1.1素数
1.1.1素数筛法(欧拉筛法,判断 1.1.2素数筛法(埃氏筛法,判断 1.2最大公约数 1.3快速幂 1.3.1普通快速幂 1.3.2矩阵快速幂 书上 2.图论 2.1最短路 2.1.1Dijkstra单源最短路 权值非负 2.1.2Bellman—Ford判环 2.1.3Floyd多源最短路 2.1.4次短路算法 2.1.5双权值求花费 2.2最小(大)生成树 2.2.1Prim算法 2.2.2Kruskal算法 2.3强连通分量 2.3.1Tarjan算法 2.3.2 Kosaraju算法(解决2-SAT问题) 3.数据结构 3.1线段树 3.1.1单点更新的线段树 3.1.2区间更新的线段树 3.2二维树状数组 4.字符串处理 4.1KMP算法 4.2Manacher算法 5.搜索 5.1广搜 5.2二分查找 6.其他 6.1头文件及宏定义 6.2输入输出加速 6.3文件输入输出 6.4STL库 6.4.1set及multiset 6.4.2map /*
*notprime是一张表,false表示是素数,true表示不是素数
*prime是素数表,储存小于maxn的全部素数。
*/
const int maxn = 10500000;
int prime[maxn];
bool notprime[maxn];
int Euler(int _n) //欧拉筛法求素数,时间复杂度为O(n)。
{
int cnt = 0;
memset(notprime, 0, sizeof notprime);
memset(prime, 0, sizeof prime);
for (int i = 2; i <= _n; i++)
{
if(!notprime[i])
prime[cnt++] = i;
for (int j = 0; j < cnt && i*prime[j] <= _n; j++)
{
notprime[i*prime[j]] = true;
if (i % prime[j] == 0) break;
}
}
return cnt;
}
/*
*notprime是一张表,false表示是素数,true表示不是素数
*prime是素数表,储存小于maxn的全部素数。
*/
const int maxn = 10500000;
int prime[maxn];
bool notprime[maxn];
int Eratosthenes(int _n) //埃拉托斯特尼筛法,时间复杂度为O(nloglogn).
{
int cnt = 0;
memset(notprime, 0, sizeof notprime);
memset(prime, 0, sizeof prime);
for(int i = 2; i <= _n; i++)
{
if(!notprime[i])
{
prime[cnt++] = i;
for (int j = i+i; j <= _n; j += i)
{
notprime[j] = true;
}
}
}
return cnt;
}
int gcd(int big, int small)
{
if (small > big) swap(big, small);
int temp;
while (small != 0){ // 辗转相除法
if (small > big) swap(big, small);
temp = big % small;
big = small;
small = temp;
}
return big;
}
int power(long long a, int n)
{
long long ans = 1;
while(n > 0) {
if(n&1) {
ans *= a;
ans %= mod;
}
a *= a%mod;
a %= mod;
n /= 2;
}
return ans%mod;
}
int n, m, s, t;
int len;
struct road
{
int u, v, cost;
int next;
};
struct node
{
int v;
int len;
int cost;
node(int v, int l, int c):v(v),len(l),cost(c){}
friend bool operator <(node a, node b)
{
return a.cost>b.cost;
}
};
road G[maxn*5];
int head[maxn];
int dist[maxn];
bool vis[maxn];
void addroad(int u, int v, int cost)//加边
{
G[len].u = u;
G[len].v = v;
G[len].cost = cost;
G[len].next = head[u];
head[u] = len++;
}
void dij()
{
fill(dist, dist+n+1, INF);
dist[1] = 0;
priority_queue
int n, m, s, t;
int len;
struct road
{
int u, v, cost;
int next;
};
struct node
{
int v;
int len;
int cost;
node(int v, int l, int c):v(v),len(l),cost(c){}
friend bool operator <(node a, node b)
{
return a.cost>b.cost;
}
};
road G[maxn*5];
int head[maxn];
int dist[maxn];
bool vis[maxn];
void addroad(int u, int v, int cost)
{
G[len].u = u;
G[len].v = v;
G[len].cost = cost;
G[len].next = head[u];
head[u] = len++;
}
int bellman_ford()
{
int res;
fill(dist, dist+n+1, INF);
dist[1] = 0;
for(int i = 0; i < n; i++)
{
for(int k = 0; k < len; k++)
{
road e = G[k];
if(dist[e.v] > dist[e.u] + e.cost)
{
dist[e.v] = dist[e.u] + e.cost;
if(i == n-1)
{
return 0;
}
}
}
}
return 1;
}
int G[maxn][maxn];//储存e(i,j)的权值,不存在边时设为INF,其中G[i][i]==0
void floyd()
{
for(int k = 0; k <= mx; k++)
{
for(int i = 0; i <= mx; i++)
{
for(int j = 0; j <= mx; j++)
{
G[i][j] = min(G[i][j], G[i][k] + G[k][j]);
}
}
}
}
int n, m, s, t;
int len;
struct road
{
int u, v;
int next;
int cost;
};
struct node
{
int v;
int cost;
node(int v, int c):v(v),cost(c){}
friend bool operator <(node a, node b)
{
return a.cost>b.cost;
}
};
road G[200500];
int head[maxn];
int dist[maxn];
int dist2[maxn];
void dij()
{
fill(dist2, dist2+n+1,INF);
fill(dist, dist+n+1,INF);
dist[1] = 0;
priority_queue
/*
*注意:在本模板中 len表示路长,cost表示花费。
*/
int n, m, s, t;
int len;
struct road
{
int u, v, len, cost;
int next;
};
struct node
{
int v;
int len;
int cost;
node(int v, int l, int c):v(v),len(l),cost(c){}
friend bool operator <(node a, node b)
{
if(a.len == b.len)
return a.cost>b.cost;
return a.len>b.len;
}
};
road G[maxn*5];
int head[maxn];
int mx = -INF;
int dist[maxn];
int cost[maxn];
int path[maxn];
void addroad(int u, int v, int l, int cost)
{
G[len].u = u;
G[len].v = v;
G[len].len = l;
G[len].cost = cost;
G[len].next = head[u];
head[u] = len++;
}
int dij()
{
int res = 0;
fill(dist, dist+n+1, INF);
fill(path, path+n+1, -1);
fill(cost, cost+n+1, 0);
dist[1] = 0;
priority_queue
int n, m, s, t;
int road[maxn][maxn];//储存e(i,j)的权值,不存的边设为INF
bool vis[maxn];//标记是否属于集合X
int dist[maxn];//从集合X出发到每个顶点最小距离
int prim()
{
memset(vis, 0, sizeof vis);
fill(dist, dist+maxn, INF);
dist[1] = 0;
int res = 0;
while(1)
{
int v = -1;
//从不属于X的定点中取出从距X最近的定点
for(int i = 1; i <= n; i++)
{
if(!vis[i] &&(v==-1|| dist[i] < dist[v])) v = i;
}
if(v == -1) break;
vis[v] = true;//把顶点v加入X
res += dist[v];//更新结果
for(int i = 1; i <= n; i++)
{
dist[i] = min(dist[i], road[v][i]);//更新dist数组
}
}
return res;
}
int n, m, s, t;
int len;
struct road
{
int u, v, cost;
};
road G[maxn*5];
int par[maxn<<1];
void init()
{
for(int i = 0; i < maxn<<1; i++) par[i] = i;
}
int Find(int x)
{
return par[x]==x? x : par[x] = Find(par[x]);
}
bool same(int x, int y)
{
int fx = Find(x), fy = Find(y);
if(fx == fy)return true;
else return false;
}
void unite(int x, int y)
{
int fx = Find(x), fy = Find(y);
if(fx == fy) return;
else{
par[fx] = fy;
return;
}
}
bool cmp(road a, road b)
{
return a.cost>b.cost;
}
int kruskal()
{
sort(G, G+len, cmp);
init();
int res = 0;
for(int i = 0; i < len; i++)
{
road e = G[i];
if(!same(e.u, e.v))
{
unite(e.u, e.v);
res+=e.cost;
}
}
return res;
}
int n, m;
struct edge
{
int u, v;
int next;
};
edge G[maxn<<3];
int h[maxn];
int dfn[maxn];
int low[maxn];
int color[maxn];
bool vis[maxn];
int tot, len, out, sum;
stack
int n, m;
vector
int n, m, t, _n;
int dat[maxn<<2];
void build(int root, int left, int right)
{
if(left == right)
{
dat[root] = 1;
return;
}
int mid, rt;
mid = (left+right)>>1;
rt = root<<1;
build(rt, left, mid);
build(rt|1, mid+1, right);
dat[root] = dat[rt] + dat[rt|1];
}
void Update(int pos, int val, int root, int left, int right)
{
if(left==right)
{
dat[root] = val;
return;
}
int m=(left+right)>>1;
if(pos <= m) Update(pos, val, root<<1, left, m);
else Update(pos, val, root<<1|1, m+1, right);
dat[root] = dat[root<<1] + dat[root<<1|1];
}
int query(int qleft, int qright, int root, int left, int right)
{
if(qleft<=left && right<=qright)
{
return dat[root];
}
int m = (left+right)>>1;
int ans = 0;
if(qleft <= m ) ans += query(qleft, qright, root<<1, left, m);
if(qright > m) ans += query(qleft, qright, root<<1|1, m+1, right);
return ans;
}
int n, m, t, _n;
struct node
{
long long num;
long long lazy;
};
node dat[maxn<<2];
long long arr[maxn];
void build(int k, int l, int r)
{
if(l==r)
{
dat[k].num = arr[l];
dat[k].lazy = 0;
return;
}
build(k<<1, l, (l+r)/2);
build(k<<1|1, (l+r)/2+1, r);
dat[k].num = dat[k<<1].num + dat[k<<1|1].num;
}
void update(int a, int b, long long val, int k, int l, int r)//区间加减
{
if(rm) ans+=query(a,b,k<<1|1,m+1,r);
return ans;
}
int n, w, h, s, t;
int bit[maxn][maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int x, int y, int v)
{
for(int i = x; i <= h; i+=lowbit(i))
{
for(int j = y; j <= w; j+=lowbit(j))
{
bit[i][j] += v;
}
}
}
int query(int x, int y)
{
int res = 0;
for(int i = x; i; i-=lowbit(i))
{
for(int j = y; j; j-=lowbit(j))
{
res+=bit[i][j];
}
}
return res;
}
//未改进的KMP算法代码实现
void get_next(int *next, char *T, int len)
{
next[0] = -1;//-1代表没有重复子串
int k = -1;
for (int q = 1; q <= len; q++)
{
while (k > -1 && T[k+1] != T[q])//下一个元素不相等,把k向前回溯
{
k = next[k];
}
if (T[k+1] == T[q])//下一个元素相等,所以最长重复子串+1
{
k = k+1;
}
next[q] = k;//给next数组赋值
}
}
int KMP(char *s, int len, char *p, int plen)//利用KMP算法匹配
{
int *next = new int(plen);
get_next(next, p, plen);
int k = -1;
int i = 0;
for (; i < len; i++)
{
while (k > -1 && p[k+1]!=s[i])//两串下一个字符不相等,向前回溯(效率高就是在这里,每次匹配失败,
//k不用直接变为0,从第一个字符开始重新匹配,而是变为最长重复子串的下一个字符,从中间开始匹配即可)。
{
k = next[k];
}
if(p[k+1] == s[i])//两个串的字符相等,k+1来匹配子串的一个字符
{
k++;
}
if (k == plen-1)//匹配成功,返回短串在长串的位置。
{
return i-plen+1;
}
}
return -1;
}
/*
* 求最长回文子串
*/
const int MAXN=110010;
char Ma[MAXN*2];
int Mp[MAXN*2];
void Manacher(char s[],int len){
int l=0;
Ma[l++]='$';
Ma[l++]='#';
for(int i=0;i
int move[4][2] = {1,0,0,1,-1,0,0,-1};//遍历四个方向
struct node
{
int x, y, step;//x,y是坐标,t是步数.
node(int _x, int _y, int _step){x = _x; y= _y; step=_step;}
node(){}
};
int h, w, sx, sy, gx, gy;
int map[500][500];
bool visit[500][500];
int bfs()
{
memset(visit, 0, sizeof(visit));
queue
/*
|二分搜索|
|要求:先排序|
*/
// l为最开始元素, r是末尾元素,x是要找的数
int bsearch(int *A, int l, int r, int val){
int m;
while (l < r){
if(l==r)
{
if(A[l] == val)
return l;
else
return -1;
}
m = (l + r) / 2;
if (A[m] >= val) r = m; else l = m + 1;
}
return -1;
}
/*
最后l == r
如果找有多少的x,可以用lower_bound查找一遍,upper_bound查找一遍,下标相减
C++自带的lower_bound(a,a+n,x)返回数组中最后一个x的下一个数的地址
upper_bound(a,a+n,x)返回数组中第一个x的地址
如果a+n内没有找到x或x的下一个地址,返回a+n的地址
lower_bound(a,a+n,x)-upper_bound(a,a+n,x)返回数组中x的个数
*/
#include
std::ios::sync_with_stdio(false);
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
//set及multiset用法(后者允许重复)
//主要函数:
begin() //返回指向第一个元素的迭代器
clear() //清除所有元素
count() //返回某个值元素的个数
empty() //如果集合为空,返回true
end() //返回指向最后一个元素的迭代器
erase() //删除集合中的元素(参数是一个元素值,或者迭代器)
find() //返回一个指向被查找到元素的迭代器
insert() //在集合中插入元素
size() //集合中元素的数目
lower_bound() //返回指向大于(或等于)某值的第一个元素的迭代器
upper_bound() //返回大于某个值元素的迭代器
equal_range() //返回集合中与给定值相等的上下限的两个迭代器
//(注意对于multiset 删除操作之间删除值会把所以这个值的都删掉,删除一个要用迭代器)
begin() //返回指向map头部的迭代器
clear()// 删除所有元素
count()// 返回指定元素出现的次数
empty() //如果map为空则返回true
end() //返回指向map末尾的迭代器
equal_range()// 返回特殊条目的迭代器对
erase() //删除一个元素
find() //查找一个元素
insert() //插入元素
lower_bound() //返回键值>=给定元素的第一个位置
max_size() //返回可以容纳的最大元素个数
rbegin() //返回一个指向map尾部的逆向迭代器
rend() //返回一个指向map头部的逆向迭代器
size() //返回map中元素的个数
swap()// 交换两个map
upper_bound()// 返回键值>给定元素的第一个位置
value_comp() //返回比较元素value的函数
for(auto i = mp.begin(); i != mp.end(); i++)//遍历,i为pair类型 访问用'.'
map