自定义头文件

Mars_Dingdang

2020-12-19 16:22:59

Personal

## 自定义头文件使用介绍 ### 一、代码主体 ```cpp struct Bignum{ int len,s[maxm]; Bignum(){ len=1; memset(s,0,sizeof(s)); } Bignum operator =(const char *num){ len=strlen(num); rep(i,0,len-1) s[i]=(num[len-i-1]^48); return *this; } Bignum operator =(const int num){ char a[maxm]; sprintf(a,"%d",num); *this = a; return *this; } Bignum(int num){*this = num;} Bignum(const char *num){*this = num;} Bignum operator +(const Bignum &a){ Bignum c; c.len=max(len,a.len)+1; for(int i=0,x=0;i<c.len;i++){ c.s[i]=s[i]+a.s[i]+x; x=c.s[i]/10; c.s[i]%=10; } if(c.s[c.len-1]==0) c.len--; return c; } Bignum operator +=(const Bignum &a){ *this = *this + a; return *this; } Bignum operator *(const Bignum &a){ Bignum c; c.len=len+a.len; rep(i,0,len-1) { rep(j,0,a.len-1) { c.s[i+j] += s[i]*a.s[j]; c.s[i+j+1] += c.s[i+j]/10; c.s[i+j] %= 10; } } if(c.s[c.len-1]==0) c.len--; return c; } Bignum operator *=(const Bignum &a){ *this = *this * a; return *this; } bool operator <(const Bignum &x)const{ if(len!=x.len) return len<x.len; for(int i=len-1;i>=0;i--) if(s[i]!=x.s[i]) return s[i]<x.s[i]; return false; } bool operator >(const Bignum &x)const{return x<*this;} bool operator <=(const Bignum &x)const{return !(x<*this);} bool operator >=(const Bignum &x)const{return !(*this<x);} bool operator ==(const Bignum &x)const{return !(*this<x||x<*this);} bool operator !=(const Bignum &x)const{return (*this<x||x<*this);} }; ostream& operator <<(ostream &out,const Bignum &x){ for(int i=x.len-1;i>=0;i--) cout<<x.s[i]; return out; } istream& operator >>(istream &in,Bignum &x){ char num[maxm]; in>>num; x=num; return in; } class PrimeNumber{ public: int tot=0,prime[maxn]={0}; bool a[maxn]={0}; inline bool isPrime(int x){ if(x<=1) return 0; if(x==2) return 1; else if(!(x&1)) return 0; for(int i=3;i*i<=x;i+=2) if(x%i==0) return 0; return 1; } inline void EulerFind(int n){ memset(a,1,sizeof(a)); a[0]=a[1]=false; for(int i=2;i<=n;i++){ if(a[i]==true){ prime[++tot]=i; } for(int j=1;j<=tot;j++){ int t=i*prime[j]; if(t>n) break; a[t]=false; if(i%prime[j]==0) break; } } }//欧拉筛 }; class Dijkstra{ private: struct node{ int w,now; bool operator <(const node &x)const{ return w>x.w; } }; priority_queue<node> q; public: struct Edge{ int from,to,w,next; }e[maxn]; int head[maxn],tot,dis[maxn],s; bool vis[maxn]; inline void add(int u,int v,int w){ e[++tot].from=u; e[tot].to=v; e[tot].w=w; e[tot].next=head[u]; head[u]=tot; } inline void dijkstra(){ memset(dis,0x3f3f3f3f,sizeof(dis)); dis[s]=0; q.push((node){0,s}); while(!q.empty()){ node x=q.top();q.pop(); int u=x.now; if(vis[u]) continue; vis[u]=1; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; q.push((node){dis[v],v}); } } } } }; class KMP{ public: int n,m; char a[maxn],b[maxn]; inline void pre(){ n=strlen(a+1); m=strlen(b+1); p[1]=0; now=0; rep(i,1,m-1){ while(now>0 && b[now+1]!=b[i+1]) now=p[now]; if(b[now+1]==b[i+1]) now++; p[i+1]=now; } } inline void find(){ now=0; rep(i,0,n-1){ while(now>0 && b[now+1]!=a[i+1]) now=p[now]; if(b[now+1]==a[i+1]) ++now; if(now==m){ printf("%d\n",(i+1)-m+1); now=p[now]; } } rep(i,1,m) printf("%d ",p[i]); } int p[maxn],now; }; class ST{ public: int n,m,a[maxn]; inline void init(){ n=read(),m=read(); rep(i,1,n) a[i]=read(); l[0]=-1;//l[i]= int [log2(i)] rep(i,1,n) { f[i][0]=a[i]; l[i]=l[i>>1]+1; } rep(j,1,maxl) { for(int i=1;i+(1<<j)-1<=n;i++) f[i][j]=max(f[i][j-1],f[i+(1<<j-1)][j-1]);//Time: O(NlogN) } } inline int query(int x,int y){ int k=l[y-x+1]; return max(f[x][k],f[y-(1<<k)+1][k]);// Time: O(1) } private: #define re register #define gg (getchar()) inline int read(){ register int x=0,f=1; re char c=gg; while(!isdigit(c)){ if(c=='-') f=-1; c=gg; } while(isdigit(c)){ x=(x<<1)+(x<<3)+(c^48); c=gg; } return x*f; } #undef re #undef gg int l[maxn],f[maxn][maxl+5];//Memory: O(NlogN) }; inline long long Pow(int a,int x){ long long ans=1; while(x){ if(x&1) ans*=a; a*=a; x>>=1; } return ans; } class BinaryIndexTree{ private: int c[maxn]; inline int lowbit(int x){return x&(-x);} public: #define Max(a,b) (a>b?a:b) int n; inline void update(int x,int v){ for(;x<=n;x+=lowbit(x)) c[x]+=v; } inline int sum(int x) { int res=0; for(;x;x-=lowbit(x)) res+=c[x]; return res; } #undef Max(a,b) }; #define re register #define gg (getchar()) inline ll input(){ register ll x=0,f=1; re char c=gg; while(!isdigit(c)){ if(c=='-') f=-1; c=gg; } while(isdigit(c)){ x=(x<<1)+(x<<3)+(c^48); c=gg; } return x*f; } #undef re #undef gg struct SegmentTree{ ll add[maxn<<2]={0},sum[maxn<<2]={0},mul[maxn<<2]={0},a[maxn]; inline void pushdown(ll k,ll l,ll r){ if(!add[k] && mul[k]==1) return ; ll len=r-l+1; sum[k<<1]=(sum[k<<1]*mul[k]+add[k]*(len-(len>>1)))%mod; sum[k<<1|1]=(sum[k<<1|1]*mul[k]+add[k]*(len>>1))%mod; add[k<<1]=(add[k<<1]*mul[k]+add[k])%mod; add[k<<1|1]=(add[k<<1|1]*mul[k]+add[k])%mod; (mul[k<<1]*=mul[k])%=mod; (mul[k<<1|1]*=mul[k])%=mod; add[k]=0;mul[k]=1; } inline void build(ll k,ll l,ll r){ add[k]=0;mul[k]=1; if(l==r){ sum[k]=a[l]%mod; return ; } ll mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); sum[k]=sum[k<<1]+sum[k<<1|1];sum[k]%=mod; } inline void multiply(ll k,ll l,ll r,ll x,ll y,ll v){ pushdown(k,l,r); if(x<=l&&y>=r){ (sum[k]*=v)%=mod; (mul[k]*=v)%=mod; return ; } ll mid=(l+r)>>1; if(x<=mid) multiply(k<<1,l,mid,x,y,v); if(y>mid) multiply(k<<1|1,mid+1,r,x,y,v); sum[k]=sum[k<<1]+sum[k<<1|1];sum[k]%=mod; } inline void update(ll k,ll l,ll r,ll x,ll y,ll v){ pushdown(k,l,r); if(l==r){ (sum[k]+=v*(r-l+1))%=mod; (add[k]+=v)%=mod; return ; } ll mid=(l+r)>>1; if(x<=mid) update(k<<1,l,mid,x,y,v); if(y>mid) update(k<<1|1,mid+1,r,x,y,v); sum[k]=(sum[k<<1]+sum[k<<1|1])%mod; } inline ll query(ll k,ll l,ll r,ll x,ll y){ pushdown(k,l,r); if(x<=l&&y>=r) return sum[k]; ll mid=(l+r)>>1; ll res=0; if(x<=mid) (res+=query(k<<1,l,mid,x,y))%=mod; if(y>mid) (res+=query(k<<1|1,mid+1,r,x,y))%=mod; return res; } }; class MST{ private: int fa[maxn],n=0,m=0,ans=0; inline int find(int k){ if(k==fa[k]) return fa[k]; return fa[k]=find(fa[k]); } public: struct node{ int u,v,w; bool operator <(const node &x)const{ return w<x.w; } }a[maxn]; inline void kruskal(){ rep(i,1,n) fa[i]=i; int cnt=0; rep(i,1,m) { int f1=find(a[i].u); int f2=find(a[i].v); if(f1!=f2) { ans+=a[i].w; fa[f2]=f1; cnt++; if(cnt==n-1) break; } } } //<------------Kruskal--------------> const int inf=0x3f3f3f3f; struct Edge{ int from,to,w,next; }e[maxn]; int head[maxn],dis[maxn],tot,cnt; bool vis[maxn]; inline void add(int u,int v,int w){ e[++tot].to=v; e[tot].w=w; e[tot].next=head[u]; head[u] = tot; } #define mp(x,y) make_pair(x,y) priority_queue< pair<int,int> > q; inline int prim(){ q.push(mp(0,1)); while(!q.empty() && cnt<=n-1){ int now=q.top().second; int w=q.top().first;q.pop(); if(vis[now]) continue; vis[now]=1; ans+=w; cnt++; for(int i=head[now];i;i=e[i].next){ int x=e[i].to; if(!vis[x]){ q.push(mp(-e[i].w,x)); } } } return -ans; } #undef mp(x,y) //<-------------prim---------------> }; #undef rep(ii,aa,bb) ``` ### 二、功能介绍 本头文件基本包含了 c++ 常备头文件,如 `iostream`, `cstdio`, `cmath`, `algorithm` 等,可以实现库函数和 STL 的直接调用实现。更进一步地了解可以使用的库函数和 STL 容器请自行百度(由于这些均是已开发头文件)。 STL 容器大致包含了 `vector`, `map`, `queue`, `priority_queue`, `stack`, `string`, `set`等常用模板库。当然也可以自行更改 `Mars.h` 以添加。 接下来重点介绍手写的封装数据结构: 1. 变量(常量)等可直接调用函数: - 长整型 `ll`; - 数值范围 `maxm=4000`用于高精位数,`maxn=1e5+5`, `maxl=20`用于 RMQ, `mod=1e9+7`; - 循环简化 `rep(i,a,b)`; - 读入优化 `ll input()`; - 快速幂 `ll Pow(int,int)`; 2. 手写数据结构: - 高精加法乘法 `Bignum`,包括输入输出流的定义 - 质数 `PrimeNumber` 中包含判断函数 `bool isPrime(int)` $O(\sqrt n)$,以及欧拉筛 `void EulerFind(int)`; - 最短路 `Dijkstra` 中包含链式前向星连边操作 `add` 与 `dijkstra` 函数,$O((n+m)\log m)$; - `KMP` 基本函数 - RMQ 问题的 `ST` 中包含初始化 `void init()` 与查询最大值 `int query(int,int)`; - 树状数组 `BinaryIndexTree` 的单点修改 `void update(int,int)` 和前缀和查询 `int sum(int)`; - 线段树 `SegmentTree`; - 最小生成树 `MST` 的 `void kruskal()`, `prim()`。