欢迎打脸~
数论
exgcd
int exgcd(int a,int b,int &x,int&y){//ax+by=0
if(b==0){ //a,b已知
x=1;y=0;
return a;
}
int t=exgcd(b,a%b,x,y);
int p=x;
x=y;y=p-a/b*y;
return t;
}
欧拉函数
求一个
int phi(int x){
int ans=x;
for(int i=2;i*i<=x;i++)
if(x%i==0){
ans-=ans/i;
while(x%i==0)
x/=i;
}
return x>1?ans-ans/x:ans;
}
线性求+欧拉筛
int pri[maxn],phi[maxn],cnt;
bool isp[maxn];
void oula(){
phi[1]=1;
for(int i=2;i<=n;i++){
if(!isp[i]){
pri[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&pri[j]*i<=n;j++){
isp[pri[j]*i]=1;
if(i%pri[j]==0){
phi[pri[j]*i]=phi[i]*pri[j];
break;
}
else
phi[pri[j]*i]=phi[pri[j]]*phi[i];
}
}
}
BSGS
aans=n(mod p)
可改map
int BSGS(int a,int n,int p){
unordered_map<int,int> hs;
unordered_map<int,int>::iterator it;
int m=ceil(sqrt(p));
int v=1;
for(int i=0;i<m;i++){
hs[n*v%p]=i;
v=v*a%p;
}
int d=v;
for(int i=1;i<=m;i++){
it=hs.find(d);
if(it!=hs.end())
return i*m-it->second;
d=d*v%p;
}
return -1;
}
逆元
int inv(int a,int p){
int x,y,d;
d=p/exgcd(a,p,x,y);
return (x%d+d)%d;
}
线性求莫比乌斯函数
int pri[maxn],miu[maxn],cnt;
bool isp[maxn];
void mobius(){
miu[1]=1;
for(int i=2;i<=n;i++){
if(isp[i]==0){
miu[i]=-1;
pri[++cnt]=i;
}
for(int j=1;j<=cnt&&i*pri[j]<=n;j++){
isp[i*pri[j]]=1;
if(i%pri[j]==0)
break;
miu[i*pri[j]]=-miu[i];
}
}
}
数据结构
树状数组
int lowbit(int x){
return x&-x;
}
void add(int pos,int v){
while(pos<=n){
t[pos]+=v;
pos+=lowbit(pos);
}
}
int getsum(int *t,int pos){
int sum=0;
while(pos){
sum+=t[pos];
pos-=lowbit(pos);
}
return sum;
}
线段树
int t[4*maxn],lz[4*maxn];
void build(int p=1,int cl=1,int cr=n){
..........
if(cl==cr)
return ;
int mid=cl+cr>>1;
build(p<<1,cl,mid);
build(p<<1|1,mid+1,cr);
pushup(p);
}
void pushup(int p){
........
}
void pushdown(int p){
........
}
void update(int l,int r,int d,int p=1,int cl=1,int cr=n){
if(cl>=l&&cr<=r){
........
return ;
}
pushdown(p);
int mid=cl+cr>>1;
if(mid>=l) update(l,r,d,p<<1,cl,mid);
if(mid<r) update(l,r,d,p<<1|1,mid+1,cr);
pushup(p);
}
int query(int l,int r,int p=1,int cl=1,int cr=n){
if(cl>=l&&cr<=r)
return ...;
pushdown(p);
int mid=cl+cr>>1;
int ans=....;
if(mid>=l) ans...query(l,r,p<<1,cl,mid);
if(mid<r) ans...querY(l,r,p<<1|1,mid+1,cr);
return ans;
}
重链剖分
void pushup(int p){
......
}
void pushdown(int p){
if(lz[p]==0)
return;
......
}
void update(int k,int d,int p=1,int cl=1,int cr=n){
if(cl==cr){
......
return ;
}
pushdown(p);
int mid=cl+cr>>1;
if(mid>=k) update(k,d,p<<1,cl,mid);
else update(k,d,k<<1|1,mid+1,cr);
pushup(p);
}
int query(int l,int r,int p=1,int cl=1,int cr=n){
if(l<=cl&&r>=cr)
return ...;
pushdowm(p);
int mid=cl+cr>>1;
if(mid>=l) .......query(l,r,p<<1,cl,mid);
if(mid<r) .......query(l,r,p<<1|1,mid+1,cr);
return ...;
}
void dfs(int x,int f){
fa[x]=f;size[x]=1;deep[x]=deep[f]+1;
int maxson=-1;
for(int i=head[x];i;i=e[i].next){
int to=e[i].v;
if(f==to)
continue;
dfs1(to,x);
if(size[to]>maxson){
maxson=size[to];
son[x]=to;
}
size[x]+=size[to];
}
}
void dfs2(int x,int top){
dfn[x]=++num;
topf[x]=top;
if(son[x])
dfs2(son[x],top);
for(int i=head[x];i;i=e[i].next){
int to=e[i].v;
if(to==fa[x]||to==son[x])
continue;
dfs2(to,to);
}
}
void solve(int a,int b){
while(topf[a]!=topf[b]){
if(deep[topf[a]]<deep[topf[b]])
swap(a,b);
update(dfn[topf[a]],dfn[a])
a=fa[topf[a]];
}
if(a==b)
return;
if(deep[a]<deep[b])
swap(a,b);
update(dfn[son[b],dfn[a]);
)
图论
最短路
Floyd
void Floyd(){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
g[i][j]=min(g[i][k]+g[k][j],g[i][j]);
}
dijkstra
bool vis[maxn];
struct node{
int id,d;
bool operator <(const node &x)const{return x.d<d;}
};
int dijkstra(int s,int t){
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
priority_queue<node> q;
dis[s]=0;
q.push((node){s,0});
while(!q.empty()){
int xid=q.top().id;
int xd=q.top().d;
q.pop();
if(vis[xid])
continue;
vis[xid]=1;
for(int i=head[xid];i;i=e[i].next)
if(dis[xid]+e[i].wi<dis[e[i].val]){
dis[e[i].val]=dis[xid]+e[i].wi;
q.push((node){e[i].val,dis[e[i].val]});
}
}
return dis[t];
}
SPFA
bool vis[maxn];
struct node{
int id,d;
};
int spfa(int s,int t){
memset(vis,0,sizeof(vis));
memset(dis,0x3f,sizeof(dis));
queue<node> q;
dis[s]=0;
q.push((node){s,0});
while(!q.empty()){
int xid=q.front().id;
int xd=q.front().d;
q.pop();
vis[xid]=0;
for(int i=head[xid];i;i=e[i].next)
if(dis[xid]+e[i].wi<dis[e[i].val]){
dis[e[i].val]=dis[xid]+e[i].wi;
if(vis[e[i].val]==0){
vis[e[i].val]=1;
q.push((node){e[i].val,dis[e[i].val]});
}
}
}
return dis[t];
}
最小生成树
Prim
struct node{
long long w;
int id;
bool operator <(const node &x)const {return x.dis<dis;}
}
void Peim(){
priority_queue<node> q;
q.push((node){1,1});
while(!q.empty()){
now=q.top();
q.pop();
if(vis[now.id])
continue;
vis[now.id]=1;
ans+=now.dis;
for(int i=head[now.id];i;i=e[i].next){
to=e[i].val;
if(dis[to]<=e[i].w)
continue;
dis[to]=e[i].w;
q.push((node){e[i].w,e[i].val});
}
kruskal
int find(int x){
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
bool cmp(edge x,edge y){
return x.w<y.w;
}
void kruskal(){
sort(e+1,e+1+cnt,cmp);
for(int i=1;i<=cnt;i++){
int a=find(e[i].id);
int b=find(e[i].val);
if(a==b)
continue;
ans+=e[i].w;
fa[x]=y;
}
}
图的连通性问题
边双连通分量
void dfs(int x,int f){
if(dfn[x])
return ;
low[x]=dfn[x]=++num;
sta[++top]=x;
for(int i=head[x];~i;i=e[i].next){
int to=e[i].val;
if(f^1==i)
continue;
if(!dfn[to]){
dfs(to,i);
low[x]=min(low[x],low[to];
}
else
low[x]=min(low[x],dfn[to]);
}
if(low[x]==dfn[x]){
tot++;
while(sta[top+1]!=x){
c[sta[top]]=tot;
top--;
}
}
}
点双连通分量
void dfs(int x,int f){
int sum=0;
num++;
low[x]=dfn[x]=num;
sta[++top]=x;
for(int i=head[x];i;i=e[i].next){
int to=e[i].val;
if(i==f^1)
continue;
if(!dfn[to]){
sum++;
dfs(to,i);
low[x]=min(low[x],low[to]);
if(low[to]>=dfn[x]){
tot++;
while(sta[top+1]!=to){
s[tot].push_back(sta[top]);
top--;
}
s[tot].push_back(x);
}
}
else
low[x]=min(low[x],dfn[to]);
}
if(f==-1&&!sum){
tot++;
s[tot].push_back(x);
return ;
}
}