各类模板
矩阵乘法
Matrix,支持二维 initializer_list 初始化。支持矩阵加法、矩阵乘法。重载 +、+=、*、*=。
参考代码
struct Matrix{
int n,m;
int a[3][3];
Matrix(int nn=-1,int mm=-1){
if(mm==-1){
mm=nn;
}
if(nn!=-1){
n=nn,m=mm;
}else{
n=0,m=0;
}
memset(a,0,sizeof(a));
}
Matrix(initializer_list<initializer_list<int>> x){
n=x.size();m=0;
for(auto &i:x){
m=max(m,(int)i.size());
}
int pi=0;
for(auto &i:x){
int pj=0;
for(auto &j:i){
a[pi][pj]=j;
pj++;
}
pi++;
}
}
int* operator [](const int &x){
return a[x];
}
void unit(){
memset(a,0,sizeof(a));
for(int i=0;i<n;i++){
a[i][i]=1;
}
}
void print(){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cout<<a[i][j]<<' ';
}
cout<<endl;
}
}
};
Matrix operator *(Matrix A,Matrix B){
Matrix C(A.n,B.m);
for(int i=0;i<A.n;i++){
for(int j=0;j<B.m;j++){
for(int k=0;k<A.m;k++){
C[i][j]+=A[i][k]*B[k][j];
}
}
}
return C;
}
Matrix& operator *=(Matrix &A,Matrix B){
return A=A*B;
}
Matrix operator +(Matrix A,Matrix B){
Matrix C(A.n,A.m);
for(int i=0;i<A.n;i++){
for(int j=0;j<A.m;j++){
C[i][j]=A[i][j]+B[i][j];
}
}
return C;
}
Matrix& operator +=(Matrix &A,Matrix B){
for(int i=0;i<A.n;i++){
for(int j=0;j<A.m;j++){
A[i][j]+=B[i][j];
}
}
return A;
}
计数模板
参考代码
int fact[V+1],invFact[V+1];
int qpow(int base,int n){
int ans=1;
while(n){
if(n&1){
ans=1ll*ans*base%P;
}
base=1ll*base*base%P;
n>>=1;
}
return ans;
}
void pre(){
fact[0]=1;
for(int i=1;i<=V;i++){
fact[i]=1ll*fact[i-1]*i%P;
}
invFact[V]=qpow(fact[V],P-2);
for(int i=V-1;0<=i;i--){
invFact[i]=invFact[i+1]*(i+1ll)%P;
}
}
int C(int n,int m){
if(n<0||m<0||n<m){
return 0;
}
return 1ll*fact[n]*invFact[m]%P*invFact[n-m]%P;
}
Barrett 约减
调用 Barrett.build(P) 更新模数为 P,调用 Barrett(x) 计算 x%P。
支持 \(\left[-2^{63},2^{63}\right)\) 内的整数取模,模数范围为 \([2,2^{31})\)。
参考代码
typedef long long ll;
typedef __int128 lll;
struct Barrett{
ll p,m;
inline void build(int P){
p=P;
m=((lll)1<<64)/p;
}
inline ll operator ()(ll x){
ll ans=x-((lll)x*m>>64)*p;
if(ans>=p){
ans-=p;
}
return ans;
}
}Barrett;
数据结构
并查集
参考代码
struct dsu{
int f[N+1],size[N+1];
int find(int x){
if(f[x]!=x){
return f[x]=find(f[x]);
}
return x;
}
void build(int n){
for(int i=1;i<=n;i++){
f[i]=i;
size[i]=1;
}
}
void merge(int x,int y){
x=find(x),y=find(y);
if(size[x]<size[y]){
f[x]=y;
size[y]+=size[x];
}else{
f[y]=x;
size[x]+=size[y];
}
}
}dsu;
FHQ Treap
参考代码
mt19937 Rand(time(0));
constexpr const int N=1e5;
int root;
struct FHQTreap{
int size;
struct node{
int value,size,rand;
int lChild,rChild;
}t[N+1];
FHQTreap(){
size=root=0;
}
int create(int x){
t[++size]={x,1,Rand()};
return size;
}
void up(int p){
t[p].size=t[t[p].lChild].size+t[t[p].rChild].size+1;
}
void split(int p,int x,int &l,int &r){
if(!p){
l=r=0;
return;
}
if(t[p].value<=x){
l=p;
split(t[p].rChild,x,t[p].rChild,r);
}else{
r=p;
split(t[p].lChild,x,l,t[r].lChild);
}
up(p);
}
int merge(int l,int r){
if(!l||!r){
return l|r;
}
if(t[l].rand<t[r].rand){
t[l].rChild=merge(t[l].rChild,r);
up(l);
return l;
}else{
t[r].lChild=merge(l,t[r].lChild);
up(r);
return r;
}
}
void insert(int x){
int l,r,p;
split(root,x,l,r);
root=merge(merge(l,create(x)),r);
}
void erase(int x){
int l,r,p;
split(root,x,l,r);
split(l,x-1,l,p);
p=merge(t[p].lChild,t[p].rChild);
root=merge(merge(l,p),r);
}
int rank(int x){
int l,r;
split(root,x-1,l,r);
int ans=t[l].size+1;
root=merge(l,r);
return ans;
}
int kth(int k,int p=root){
while(true){
if(t[t[p].lChild].size+1==k){
return t[p].value;
}else if(t[t[p].lChild].size+1<k){
k-=t[t[p].lChild].size+1;
p=t[p].rChild;
}else{
p=t[p].lChild;
}
}
}
int prev(int x){
int l,r;
split(root,x-1,l,r);
int ans=kth(t[l].size,l);
root=merge(l,r);
return ans;
}
int next(int x){
int l,r;
split(root,x,l,r);
int ans=kth(1,r);
root=merge(l,r);
return ans;
}
void print(int p=root){
if(!p){
return;
}
print(t[p].lChild);
cerr<<t[p].value<<' ';
print(t[p].rChild);
}
}t;
图论
链式前向星
参考代码
struct graph{
struct edge{
int v,r,w,c;
}g[M<<2|1];
int h[N+1],size=1;
void create(int u,int v,int w,int c){
g[++size]={v,h[u],w,c};
h[u]=size;
}
edge& operator [](int x){
return g[x];
}
}g;
Dijkstra
参考代码
void Dijkstra(int s,int dis[]){
static bool vis[N+1];
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>>q;
memset(vis,0,sizeof(vis));
fill(dis+1,dis+n+1,inf);
dis[s]=0;
q.push({dis[s],s});
while(q.size()){
int x=q.top().second;
q.pop();
if(vis[x]){
continue;
}
vis[x]=true;
for(auto [v,w]:g[x]){
if(dis[x]+w<dis[v]){
dis[v]=dis[x]+w;
q.push({dis[v],v});
}
}
}
}
SPFA
返回 \(1\) 表示无环,返回 \(0\) 表示有环。
参考代码
bool SPFA(int s,int dis[]){
static bool in[N+1];
static int c[N+1];
fill(dis+1,dis+n+1,inf);
queue<int>q;
q.push(s);
dis[s]=0;
in[s]=true;
while(q.size()){
int x=q.front();q.pop();
in[x]=false;
if(c[x]>=n){
return false;
}
for(auto [v,w]:g[x]){
if(dis[x]+w<dis[v]){
dis[v]=dis[x]+w;
c[v]=c[x]+1;
if(!in[v]){
in[v]=true;
q.push(v);
}
}
}
}
return true;
}

浙公网安备 33010602011771号