C++ 算法模板
文章目录
1 数据结构
1.1 线性结构
1.1.1 顺序表
typedef struct Triple{
int u,v;
int w;
}Triple;
vectror<Triple> vt;
1.2 图状结构
1.2.1 二维数组
const int maxn=;
int maze[maxn][manx];
vector<vector<int>> v;
1.2.2 二叉树
typedef struct Node{
int data;
Node *lchild,*rchild;
}Node;
1.2.3 邻接表
typedef struct Edge{
int u,v,next;
}Edge;
const int maxn=;
Edge edge[maxn];
int head[maxn],cnt=0,n;
void init(){
for(int i=0;i<n;i++){
head[i]=-1;
}
}
void addedge(int u,int v){
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
2 数论类
2.1最小公倍数
- 更相减损法
int gcd(int a,int b){
if(a==b) return a;
else return a>b?gcd(a-b,b):gcd(b-a,a);
}
int gcd(int a,int b){
while(a-b){
int c=a-b;
if(c>0) a=c;
else{
b=a;
a=-c;
}
}
return a;
}
- 辗转相除法
int gcd(int a,int b){
if(!b) return a;
return gcd(b,a%b);
}
int gcd(int a,int b){
while(b){
int c=a%b;
a=b;
b=c;
}
return a;
}
2.2 最大公约数
int gcd(int a,int b){
if(!b) return a;
return gcd(b,a%b);
}
int lcm(int a,int b){
return a*b/gcd(a,b);
}
2.3 快速幂
const long long MAX=...;
long long fastPower(long long base,long long power){
long long res=1;
while(power>0){
if(power&1==1) res=res*base%MAX;
pow>>=1;
base=base*base%MAX;
}
return res;
}
2.4 求素数
- 定义法
bool isPrime(int n){
if(n<=1) return false;
for(int i=2;i<=sqrt(n);i++){
if(n%i==0) return false;
}
return true;
}
- 埃氏筛法
const int maxn=...;
bool prime[maxn];
void sieve(){
int i,j;
for(i=0;i<maxn;i++) prime[i]=true;
prime[0]=false;
prime[1]=false;
for(i=2;i<maxn;i++){
if(prime[i]){
for(j=2*i;j<maxn;j+=i) prime[j]=false;
}
}
}
2.5 小费马定理(分数取模)
a b % p = a ∗ b p − 2 % p \large \frac{a}{b} \% p = a*b^{p-2} \% p ba%p=a∗bp−2%p
3 字符串类
3.1 模式匹配
- KMP
vector<int> getNext(string s){
int n=s.size();
vector<int> v(n);
int i=0,j=-1;
while(i<n){
if(j==-1||s[i]==s[j]){
i++;
j++;
v[i]=j;
}else{
j=v[j];
}
}
}
int kmp(string s1,string s2){
vector<int> next=getNext(s2);
int i=0,j=0;
while(i<s1.size()&&j<s2.size()){
if(j==-1||s1[i]==s2[j]){
i++;
j++;
}else{
j=next[j];
}
}
if(j==s2.size()) return i-j;
else return -1;
}
4.图论类
4.1 最短路径
4.1.1 Dijkstra
const int inf=1e9;
const int maxn=;
int arc[maxn][manx],dis[maxn];
bool vis[maxn];
int n;
void init(){
for(int i=0;i<n;i++){
dis[i]=inf;
vis[i]=false;
for(int j=0;j<n;j++){
if(i==j) arc[i][j]=0;
else arc[i][j]=inf;
}
}
}
void dijkstra(int u){
dis[u]=0;
int mini;
for(int i=0;i<N;i++){
mini=inf;
for(int j=0;j<N;j++){
if(!vis[j]&&dis[j]<mini){
u=j;
mini=dis[j];
}
}
vis[u]=true;
for(int j=0;j<N;j++){
if(!vis[j]&&arc[u][j]!=inf&&dis[u]+arc[u][j]<dis[j]){
dis[j]=dis[u]+arc[u][j];
}
}
}
}
4.1.2 Floyd
const int inf=1e9;
const int maxn=;
int arc[maxn][maxn];
int n;
void init(){
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
if(i==j) arc[i][j]=0;
else arc[i][j]=inf;
}
}
}
void floyd(){
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(arc[i][k]+arc[k][j]<arc[i][j]){
arc[i][j]=arc[i][k]+arc[k][j];
}
}
}
}
}
4.1.3 SPFA
const int inf=1e9;
const int maxn=;
vector<int> to[maxn],weight[maxn];
int dis[maxn];
bool vis[maxn];
int n,start,dest;
void spfa(int start){
int i,j;
for(i=0;i<n;i++){
dis[i]=inf;
vis[i]=false;
}
dis[start]=0;
vis[start]=true;
queue<int> Q;
Q.push(start);
while(!Q.empty()){
int u=Q.front();
Q.pop();
vis[u]=false;
for(i=0;i<to[u].size();i++){
int v=to[u][i],w=weight[u][i];
if(dis[u]+w<dis[v]){
dis[v]=dis[u]+w;
if(!vis[v]){
vis[v]=true;
Q.push(v);
}
}
}
}
}
4.2 拓扑排序
4.2.1 Kahn算法
const int maxn=;
int inDeg[maxn];//
vector<int> to[maxn],res;
int toSort(){
queue<int> q;
while(!q.empty())
q.pop();
for(int i=0;i<n;i++)
if(inDeg[i]==0)
q.push(i);
while(!q.empty()){
int now=q.front();
q.pop();
res.push_back(now);
for(int i=0;i<to[now].size();i++){
inDeg[to[now][i]]--;
if(inDeg[to[now][i]]==0)
q.push(inDeg[to[now][i]]);
}
}
return res.size()==n;
}
4.2.2 DFS
const int maxn=;
vector<int> to[maxn],res;
int parent[maxn],vis[maxn];
int n;
bool dfs(int s){
vis[s]=1;
for(int i=0;i<to[s].size();i++){
int v=to[s][i];
if(vis[v]<0) return false;
else if(!vis[v]&&!dfs(v)) return false;
parent[v]=s;
}
vis[s]=1;
res.push_back(s);
return true;
}
bool toSort(){
for(int i=0;i<n;i++){
parent[i]=-1;
vis[i]=0;
}
for(int i=1;i<=n;i++){
if(!vis[i]){
if(dfs(i)==false){
return false;
}
}
}
reverse(res.begin(),res.end());
return true;
}
4.3 树相关
4.3.1 求树中结点个数(dfs)
const int maxn=;
const int maxm=;
typedef struct{
int u,v,next;
}Edge;
Edge edge[maxm];
int head[maxn],cnt;
int n,m;
void init(){
for(int i=0;i<=n;i++){
head[i]=-1;
}
}
void addedge(int u,int v){
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
}
int num;
void dfs(int u,int pre){
num+=1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].next;
if(v==pre) continue;
dfs(v,u);
}
}
5. 高精度计算
const int MAXLEN=1001;
typedef struct {
int len;
int num[MAXLEN];
} HugeInt;
bool negative;
//大数输入
HugeInt scanHugeInt() {
string s;
HugeInt hugeInt;
cin>>s;
hugeInt.len=s.size();
for(int i=0; i<s.size(); i++) {
hugeInt.num[hugeInt.len-i]=s[i]-'0';
}
return hugeInt;
}
//大数加法
HugeInt plusHugeInt(HugeInt a,HugeInt b) {
int i;
HugeInt res;
res.len=a.len>b.len?a.len:b.len;
for(i=1;i<=res.len;i++) res.num[i]=0;
for(i=1; i<=res.len; i++) {
res.num[i]+=a.num[i]+b.num[i];
res.num[i+1]=res.num[i]/10;
res.num[i]=res.num[i]%10;
}
return res;
}
//大数减法
HugeInt minusHugeInt(HugeInt a,HugeInt b) {
int i;
HugeInt res;
negative=false;
if(a.len<b.len) {
negative=true;
} else if(a.len==b.len) {
for(i=1; i<=a.len; i++) {
if(a.num[i]<b.num[i]) {
negative=true;
break;
}
}
}
if(negative) {
HugeInt t=a;
a=b;
b=t;
}
res.len=a.len;
for(i=1; i<=res.len; i++) {
if(a.num[i]<b.num[i]) {
a.num[i+1]--;
a.num[i]+=10;
}
res.num[i]=a.num[i]-b.num[i];
}
while(res.num[res.len]==0&&res.len!=1) res.len--;
return res;
}
//高精度乘法
HugeInt mutiplyHugeInt(HugeInt a,HugeInt b) {
int i;
int x;//进位
HugeInt res;
res.len=a.len+b.len;
for(i=1; i<=res.len; i++) res.num[i];
for(i=1; i<=a.len; i++) {
x=0;
for(int j=1; j<=b.len; j++) {
res.num[i+j-1]+=a.num[i]*b.num[j]+x;
x=res.num[i+j-1]/10;
res.num[i+j-1]%=10;
}
res.num[i+b.len]=x;
}
while(res.num[res.len]==0&&res.len!=1) res.len--;
return res;
}
//高精度除法(高精度除以低精度)
HugeInt divideSmallInt(HugeInt a,int b) {
HugeInt res;
int x;//余数
res.len=a.len;
x=0;
for(int i=a.len; i>=1; i--) {
res.num[i]=(a.num[i]+x*10)/b;
x=(a.num[i]+x*10)%b;
}
while(res.num[res.len]==0&&res.len!=1) res.len--;
return res;
}
6. 其他
6.1 ST表
void REQ_init(vector<int> A){
int n=A.size();
for(int i=0;i<n;i++) f[i][0]=A[i];
for(int j=1;(1<<j)<=n;j++)
for(int i=0;i+(1<<j)-1<n;i++)
f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]);
}
int RMQ(int l,int r){
int k=0;
while((1<<(k+1))<=r-l+1) k++;
return max(f[l][k],f[r-(1<<k)+1][k]);
}
6.2 并查集
const int maxn=;
int fa[maxn];
void init(int n){
for(int i=0;i<n;i++){
fa[i]=i;
}
}
int find(int x){
while(x!=fa[x]) x=fa[x];
return x;
}
void unite(int x,int y){
x=find(x);
y=find(y);
if(x==y) return;
fa[x]=y;
}
6.3 线段树(以中间结点存储所有叶子和为例)
const int maxn=;
int tree[maxn],cnt;
int lazy[maxn];
// 建树
void build(int root,int l,int r){
if(l==r){
//初始化叶子
tree[++cnt]=0;
return;
}
int mid=(l+r)>>1;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
//中间节点存储的信息(所有后继叶子之和)
tree[root]=tree[root*2]+tree[root*2+1];
}
// lazy下传
void pushDown(int root,int l,int r){
if(lazy[root]){
int mid=(l+r)>>1;
// lazy标志下传
lazy[root*2]+=lazy[root];
lazy[root*2+1]+=lazy[root];
// lazy值更新
tree[root*2]+=(mid-l+1)*lazy[root];
tree[root*2+1]+=(r-mid)*lazy[root];
// 消除改节点lazy
lazy[root]=0;
}
}
// 区间更新
void updateRange(int root,int l,int r,int L,int R,int add){
if(l<=L&&R<=r){
//更新信息暂存lazy
lazy[root]+=add;
//更新中间节点信息
tree[root]+=(R-L+1)*add;
return;
}
pushDown(root,L,R);
int mid=(L+R)>>1;
if(mid>=l) updateRange(root*2,l,r,L,mid,add);
if(mid<r) updateRange(root*2+1,l,r,mid+1,add);
//更新中间结点信息
tree[root]=tree[root*2]+tree[root*2+1];
}
// 区间查找
int queryRange(int root,int l,int r,int L,int R){
if(l<=L&&R<=r){
// 目标段的一段子段的值
return tree[root];
}
pushDown(root,L,R);
//目标值
int sum=0;
int mid=(L+R)>>1;
if(mid>=l) sum+=queryRange(root*2,l,r,L,mid);
if(mid<r) sum+=queryRange(root*2+1,l,r,mid+1,R);
return sum;
}