板子+公式(修补中)
图方便
没有写的我会在后面打\
图论
--树相关 \
--欧拉回路
void dfs(int x,int y){
if(y!=0){
vis[x][y]++;
vis[y][x]++;
}
for(int i=1;i<=500;i++){
if(ma[i][x]!=0&&vis[i][x]<mp[i][x]) dfs(i,x);
}
lu[++tot]=x;
}
int main(){
dfs(start,0);
}
--最短路相关
----floyed最小环
int floyed(){
int minn=INF;
for(int k=1;k<=n;k++){
for(int i=1;i<k;i++){
for(int j=i+1;j<k;j++){
minn=min(minn,dis[i][j]+g[i][k]+g[k][j]);
}
}
for(int i=1;i<=n;i++){
if(i==k) continue;
for(int j=1;j<=n;j++){
if(i==j||j==k) continue;
if(dis[i][j]>dis[i][k]+dis[k][j]){
dis[i][j]=dis[i][k]+dis[k][j];
}
}
}
}
return minn;
}
----floyed传递闭包(bitset优化)
bitset<N> dp[N];
void Floyd(){
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
if(d[i][k]) d[i]|=d[k];
}
----dijkstra
priority_queue<node> q;
void dij(int s){
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
q.push({0,s});
dis[s]=0;
while(!q.empty()){
node tmp=q.top();
q.pop();
int x=tmp.pos,y=tmp.dis;
if(vis[x]) continue;
vis[x]=1;
for(int i=head[x];i;i=e[i].next){
int y=e[i].to;
if(dis[y]>dis[x]+e[i].w){
dis[y]=dis[x]+e[i].w;
if(!vis[y]) q.push((node){dis[y],y});
}
}
}
----spfa判负环
int spfa(int s){
memset(dis,0x3f,sizeof(dis));
q.push(s);
flag[s]=1;
dis[s]=0;
while(!q.empty()){
int k=q.front();
for(int i=head[k];i;i=e[i].next){
int y=e[i].to;
if(dis[y]<dis[k]+e[i].w){
dis[y]=dis[k]+e[i].w;
vis[i]=vis[k]+1;
if(vis[i]>=n) return 1;
if(!flag[y]){
q.push(y);
flag[y]=1;
}
}
}
flag[k]=0;
q.pop();
}
}
--最小生成树(kruskal)
struct edd{
int x,y,z;
}tuu[M];
struct egde{
int to,next,w;
}e[M];
int n,m,dad[N];
void add(int u,int v,int w){ }
int find(int x){ }
void kruskal(){
for(int i=1;i<=n;i++) dad[i]=i;
sort(tuu+1,tuu+m+1);
for(int i=1;i<=m;i++){
int fx=find(tuu[i].x),fy=find(tuu[i].y);
if(fx!=fy){
add(tuu[i].x,tuu[i].y,tuu[i].z);
dad[fx]=fy;
}
}
}
--拓扑排序
priority<int,vector<int>,greater<int> > q;
void tuopu(){
for(int i=1;i<=n;i++)
if(!ru[i]) q.push(i);
int num=0,x;
while(!q.empty()){
x=q.top(),num++;
ans[++tot]=x;
q.pop();
for(int i=head[x];i;i=e[i].next){
ru[e[i].to]--;
if(!ru[e[i].to]) q.push(e[i].to);
}
}
//ans数组即为拓扑序
}
--tarjan
----缩点
void tarjan(int x){
vis[x]=1,dfn[x]=low[x]=++cnt,t[++tot]=x;
for(int i=head[x];i;i=e[i].next){
if(!dfn[e[i].to]) tarjan(e[i].to);
if(vis[e[i].to]) low[x]=min(low[e[i].to],low[x]);
}
if(dfn[x]==low[x]){
sum1++;
while(1){
sum[sum1]++;
vis[t[tot]]=0;
col[t[tot--]]=sum1;
if(x==t[tot+1]) break;
}
}
}
----割点
void tarjan(int x){
//cut[i]表示点i是否为割点
dfn[x]=low[x]=++cnt;
int son=0;
for(int i=head[x];i;i=e[i].next){
if(!dfn[e[i].to]){
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
if(low[e[i].to]>=dfn[x]){
son++;
if(x!=root||son>1) cut[x]=1;
}
}
else low[x]=min(low[x],dfn[e[i].to]);
}
}
int main(){
//...
for(int i=1;i<=n;i++){
if(!dfn[i]){
root=i;
tarjan(i);
}
}
return 0;
}
----割边
void tarjan(int x,int root){
//cut[i]表示边i是否为割边
//注:使用链式前向星
dfn[x]=low[x]=++cnt;
for(int i=head[x];i;i=e[i].next){
if(!dfn[e[i].to]){
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
if(low[e[i].to]>dfn[x]) cut[i]=1;
}
else if(e[i].to!=root) low[x]=min(low[x],dfn[e[i].to]);
}
}
int main(){
//...
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i,i);
//...
return 0;
}
----点双
#include<bits/stdc++.h>
#define N 500005
#define M 4000005
using namespace std;
struct egde{
int to,next;
}e[N];
int cut[N];
int n,m,num,cnt,top,root,dfn[N],low[N],t[N];
int tot,head[N];
vector<int> dcc[N];
void add(int u,int v){
if(u==v) return;
e[++tot].to=v;
e[tot].next=head[u];
head[u]=tot;
}
void tarjan(int x){
dfn[x]=low[x]=++cnt,t[++top]=x;
if(!head[x]&&x==root){
dcc[++num].push_back(x);
return;
}
int son=0;
for(int i=head[x];i;i=e[i].next){
if(!dfn[e[i].to]){
tarjan(e[i].to);
low[x]=min(low[x],low[e[i].to]);
if(low[e[i].to]>=dfn[x]){
son++,num++;
if(x!=root||son>1) cut[x]=1;
int y;
do{
y=t[top--];
dcc[num].push_back(y);
}while(y!=e[i].to);
dcc[num].push_back(x);
}
}
else low[x]=min(low[x],dfn[e[i].to]);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++)
if(!dfn[i]){
root=i;
tarjan(i);
}
cout<<num<<"\n";
for(int i=1;i<=num;i++){
cout<<dcc[i].size()<<" ";
for(int j=0;j<dcc[i].size();j++)
cout<<dcc[i][j]<<" ";
cout<<"\n";
}
return 0;
}
----边双
#include<bits/stdc++.h>
#define N 500005
#define M 4000005
using namespace std;
struct egde{
int to,next;
}e[M];
int n,m,cnt,num,top,dfn[N],low[N],t[N];
int tot=1,head[M];
vector<int> dcc[N];
void add(int u,int v){
e[++tot].to=v;
e[tot].next=head[u];
head[u]=tot;
}
void tarjan(int x,int fa){
dfn[x]=low[x]=++cnt,t[++top]=x;
for(int i=head[x];i;i=e[i].next){
int y=e[i].to;
if(i==(fa^1)) continue;
if(!dfn[y]) tarjan(y,i);
low[x]=min(low[x],low[y]);
}
if(dfn[x]==low[x]){
num++;
int y;
do{
y=t[top--];
dcc[num].push_back(y);
}while(x!=y);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(a,b);
add(b,a);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i,0);
cout<<num<<"\n";
for(int i=1;i<=num;i++){
cout<<dcc[i].size()<<" ";
for(int j=0;j<dcc[i].size();j++){
cout<<dcc[i][j]<<" ";
}
cout<<"\n";
}
return 0;
}
--lca
----dfs序求
#define lca_min(x,y) (dfn[x]<dfn[y])?x:y
void dfs(int x,int fa){
dfn[x]=++cnt,st[cnt][0]=fa;
for(int i=head[x];i;i=e[i].next){
if(!dfn[e[i].to]) dfs(e[i].to,x);
}
}
void init(){
dfs(root,0);
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i+(1<<j-1)<=n;i++){
st[i][j]=lca_min(st[i][j-1],st[i+(1<<j-1)][j-1]);
}
}
}
int lca(int u,int v){
if(u==v) return u;
u=dfn[u],v=dfn[v];
if(u>v) swap(u,v);
lg=log2(v-u);
u++;
return lca_min(st[u][lg],st[v-(1<<lg)+1][lg]);
}
----树剖求
//树链剖分详见“图论--树链剖分”
int lca(int x,int y){
if(x==y) return x;
while(top[x]!=top[y]){
if(dep[top[x]]>=dep[top[y]]) x=fa[top[x]];
else y=fa[top[y]];
}
if(dep[x]<dep[y]) return x;
return y;
}
--二分图判定
void dfs(int x,int now){
if(cnt1==-1) return;
if(col[x]!=-1){
if(now!=col[x]) cnt1=-1;
else return;
}
col[x]=now;
if(now==0) cnt1++;
else cnt2++;
for(int i=head[x];i;i=e[i].next){
dfs(e[i].to,now^1);
if(cnt1==-1) return;
}
}
void pan(){
memset(col,-1,sizeof(col));
for(int i=1;i<=n;i++){
if(col[i]==-1){
cnt=0,cnt2=0;
dfs(i,1);
if(cnt1==-1){
cout<<"false";
return;
}
}
}
cout<<"true";
}
--树链剖分 \
请在“数据结构-线段树”寻找线段树模板的区间修改,区间查询
----路径修改(极值) \
----路径修改(求和) \
----路径查询(极值) \
----路径查询(求和) \
数学相关 \
--高斯消元 \
--数论 \
----唯一分解定理 \
----线性筛素数(+欧拉函数) \
----gcd/lcm \
----试除法求欧拉函数 \
----欧拉定理 \
----扩展欧拉定理 \
----秦九昭算法(计算多项式) \
----裴蜀定理(贝祖定理) \
----扩展欧几里得 \
----乘法逆元 \
------费马小定理求解 \
------欧拉定理求解 \
------扩展欧几里得求解 \
------线性求解 \
--组合数学 \
----排列组合 \
----lusas定理 \
----扩展lucas定理 \
----二项式反演 \
----容斥原理 \
----中国剩余定理(crt) \
----扩展中国剩余定理 \
----bsgs \
----卡特兰数 \
----prufer序列 \
数据结构 \
--st表 \
--树状数组 \
--线段树 \
--单调队列/单调栈 \
--并查集 \
动态规划(DP)
--背包DP \
--线性DP \
--区间DP \
--坐标DP \
--树形DP
```cpp void dfs(int x,int fa){ for(int i=head[x];i;i=e[i].next){//遍历子节点 dfs(e[i].to,x)//递归处理子树 //由子节点转移到父节点 } } ```--换根DP \
杂
--高精度(重载运算符)
#include<bits/stdc++.h>
#define N 10005
#define base 100000
using namespace std;
struct llong{
int len,s[N];
//定义时初始化
llong(){
len=1;
memset(s,0,sizeof(s));
}
llong(int h){
len=0;
while(h) s[++len]=h%base,h/=base;
}
//字符串、整形转高精
void str(string kkk){
len=1;
memset(s,0,sizeof(s));
int tl=kkk.size(),k=1;
for(int i=0;i<tl;i++){
s[len]+=(kkk[tl-i-1]-'0')*k,k*=10;
if(k==base) ++len,k=1;
}
}
void init(int h){
len=0;
while(h) s[++len]=h%base,h/=base;
}
//去前导零
void tui(){
while(len>1&&!s[len]) len--;
}
//高精度输入输出
void read(){
string tt;
cin>>tt;
str(tt);
}
void out(){
tui();
cout<<s[len];
for(int i=len-1;i;i--) cout<<setw(4)<<setfill('0')<<s[i];
}
//高精和高精的比较
int operator>(llong x)const{
if(x.len!=len) return len>x.len;
for(int i=len;i;i--)
if(x.s[i]!=s[i]) return s[i]>x.s[i];
return 0;
}
int operator<(llong x)const{
return x>*this;
}
int operator==(llong x)const{
return !(x>*this||*this>x);
}
int operator>=(llong x)const{
return !(x>*this);
}
int operator<=(llong x)const{
return !(*this>x);
}
// +
llong operator+(llong x)const{
llong c;
c.len=max(len,x.len)+1;
for(int i=1;i<c.len;i++){
c.s[i]+=s[i]+x.s[i];
c.s[i+1]+=c.s[i]/base;
c.s[i]%=base;
}
c.tui();
return c;
}
// -
llong operator-(llong x)const{
llong c,kkk=*this;
c.len=len;
for(int i=1;i<=c.len;i++){
c.s[i]=kkk.s[i]-x.s[i];
if(c.s[i]<0) kkk.s[i+1]--,c.s[i]+=base;
}
c.tui();
return c;
}
// *
llong operator*(llong x)const{
llong c;
c.len=len+x.len+1;
for(int i=1;i<=len;i++)
for(int j=1;j<=x.len;j++){
c.s[i+j-1]+=s[i]*x.s[j];
c.s[i+j]+=c.s[i]/base;
c.s[i+j-1]%=base;
}
c.tui();
return c;
}
// /
llong operator/(llong x)const{
llong c,yu;
c.len=len;
for(int i=len;i>=1;i--){
yu=yu*base+s[i];
int l=0,r=base,mid;
while(l<r){
mid=(l+r+1)>>1;
if(x*mid<=yu) l=mid;
else r=mid-1;
}
yu=yu-x*l,c.s[i]=l;
}
c.tui();
return c;
}
llong operator%(llong x)const{
llong yu;
for(int i=len;i>=1;i--){
yu=yu*base+s[i];
int l=0,r=base,mid;
while(l<r){
mid=(l+r+1)>>1;
(x*mid<=yu)?(l=mid):(r=mid-1);
}
yu=yu-x*l;
}
return yu;
}
//重载各种高精与低精的运算
llong operator+(int x)const{
llong c(x);
return *this+c;
}
llong operator-(int x)const{
llong c(x);
return *this-c;
}
llong operator*(int x)const{
llong c(x);
return *this*c;
}
llong operator/(int x)const{
llong c(x);
return *this/c;
}
llong operator%(int x)const{
llong c(x);
return *this%c;
}
}a,b;
int main(){
while(1){
a.read();
b.read();
cout<<"> : "<<(a>b)<<"\n";
cout<<"< : "<<(a<b)<<"\n";
cout<<">= : "<<(a>=b)<<"\n";
cout<<"<= : "<<(a<=b)<<"\n";
cout<<"= : "<<(a==b)<<"\n";
llong t1=a+b,t2=a-b,t3=a*b,t4=a/b,t5=a%b;
cout<<"a+b : ";
t1.out();
cout<<"\n";
cout<<"a-b : ";
t2.out();
cout<<"\n";
cout<<"a*b : ";
t3.out();
cout<<"\n";
cout<<"a/b : ";
t4.out();
cout<<"\n";
cout<<"a%b : ";
t5.out();
cout<<"\n";
}
}
--二分
----向左(最大值最小)
while(l<r){
int mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
----向右(最小值最大)
while(l<r){
int mid=(l+r+1)>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
--字符串输入
void read(string &t){
char d;
t="",d=getchar();
while(d=='\r'||d=='\n') d=getchar();
while(d!='\r'&&d!='\n') t+=d,d=getchar();
}
--随机数种子
struct _timeb T;
_ftime(&T);
mt19937 rand(T.millitm);
--快读快写
----快读
#define SIZE (1<<20)
#define gc() (p1==p2&&(p2=(p1=in)+fread(in,1,SIZE,stdin),p1==p2)?EOF:*p1++)
char in[SIZE],*p1=in,*p2=in;
template<typename type>
inline void read(type &x){
x=0;bool flag(0);char ch=gc();
while(!isdigit(ch))flag^=(ch=='-'),ch=gc();
while(isdigit(ch))x=(x<<1)+(x<<3)+(ch^48),ch=gc();
flag?x=-x:0;
}
#undef SIZE
#undef gc
----快写
#define SIZE (1<<20)
char out[SIZE],*p3=out;
#define fl() (fwrite(p3=out,1,SIZE,stdout))
#define pc(ch) (p3==out+SIZE&&fl(),*p3++=(ch))
template<typename type>
inline void write(type x,bool flag=1){
x<0?x=-x,pc('-'):0;
static short Stack[50],top(0);
do Stack[++top]=x%10,x/=10;while(x);
while(top)pc(Stack[top--]|48);
flag?pc('\n'):pc(' ');
}
#undef SIZE
#undef pc
#undef fl