代码模板(持续更新)
字符串:
KMP算法:
int Next[maxn]; void Get_Next(char *S,int len) { int i=0,j=-1; Next[0]=-1; while(i<len) { if(j==-1||S[i]==S[j]) { i++;j++;Next[i]=j; } else j=Next[j]; } } void KMP(char *S,char *T,int lens,int lent) { Get_Next(T,lent); int i=0,j=0; while(i<lens) { if(j==-1||S[i]==T[j]) { i++;j++; } else j=Next[j]; if(j==lent) { printf("%d\n",i-lent+1); } } }
EX_KMP:
int Next[maxn],ext[maxn]; void Get_Next(char *S,int len) { int k=0;Next[0]=len; while(k+1<len&&S[k]==S[k+1]) k++; Next[1]=k;k=1; for(int i=2;i<len;i++) { if(Next[i-k]+i<Next[k]+k) Next[i]=Next[i-k]; else { int j=max(0,Next[k]+k-i); while(i+j<len&&S[i+j]==S[j]) j++; Next[i]=j;k=i; } } } void EXKMP(char *S,char *T,int *extend,int lens,int lent) { Get_Next(T,lent); int k=0; while(k<lens&&k<lent&&S[k]==T[k]) k++; extend[0]=k;k=0; for(int i=1;i<lens;i++) { if(Next[i-k]+i<extend[k]+k) extend[i]=Next[i-k]; else { int j=max(0,extend[k]+k-i); while(i+j<lens&&j<lent&&S[i+j]==T[j]) j++; extend[i]=j;k=i; } } }
图论:
匈牙利算法:
vector<int> G[maxn]; int vis[maxn],l[maxn]; bool dfs(int u) { int len=G[u].size(); for(int i=0;i<len;i++) { int v=G[u][i]; if(!vis[v]) { vis[v]=1; if(l[v]==-1||dfs(l[v])) { l[v]=u;return true; } } } return false; } int hungary(int n) { memset(l,-1,sizeof(l)); int cnt=0; for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) cnt++; } return cnt; }
网络流:
//点从1开始编号 struct Edge { int to,flow,nxt; } edges[maxn*maxn]; int cnt,n,m; int head[maxn],dep[maxn],a[maxn][maxn]; void AddEdge(int from,int to,int flow) { cnt++;edges[cnt].to=to;edges[cnt].flow=flow; edges[cnt].nxt=head[from];head[from]=cnt; cnt++;edges[cnt].to=from;edges[cnt].flow=0; edges[cnt].nxt=head[to];head[to]=cnt; } int BFS(int s,int t) { queue<int> q; dep[s]=1;q.push(s); while(!q.empty()) { int u=q.front();q.pop(); for(int x=head[u];x!=0;x=edges[x].nxt) { if(dep[edges[x].to]==0&&edges[x].flow>0) { dep[edges[x].to]=dep[u]+1; q.push(edges[x].to); } } } return (dep[t]==0)?0:1; } int DFS(int now,int RouteMinFlow,int t) { int OldRouteMinFlow=0; if(RouteMinFlow<=0||now==t) return RouteMinFlow; for(int x=head[now];x!=0;x=edges[x].nxt) { if(dep[edges[x].to]==dep[now]+1) { int temp=DFS(edges[x].to,min(RouteMinFlow,edges[x].flow),t); edges[x+1].flow+=temp;edges[x].flow-=temp; RouteMinFlow-=temp;OldRouteMinFlow+=temp; if(RouteMinFlow==0) break; } } return OldRouteMinFlow; } int maxflow(int s,int t) { int ans=0; while(BFS(s,t)) { ans+=DFS(1,inf,t); memset(dep,0,sizeof(dep)); } return ans; } void init() { cnt=0;memset(dep,0,sizeof(dep)); memset(head,0,sizeof(head)); }
最小费用最大流:
struct Edge { int to,cap,cost,nxt; } edges[maxn*maxn]; int cnt; int d[maxn],head[maxn],pre[maxn],path[maxn]; void AddEdge(int from,int to,int cap,int cost) { edges[cnt].to=to;edges[cnt].cap=cap;edges[cnt].cost=cost; edges[cnt].nxt=head[from];head[from]=cnt++; edges[cnt].to=from;edges[cnt].cap=0; edges[cnt].cost=-cost; edges[cnt].nxt=head[to];head[to]=cnt++; } bool Spfa(int s,int t) { memset(pre,-1,sizeof(pre)); memset(d,0x3f,sizeof(d)); queue<int> q; q.push(s);d[s]=0; while (!q.empty()) { int u=q.front();q.pop(); for(int e=head[u];e!=-1;e=edges[e].nxt) { int v=edges[e].to; if(edges[e].cap>0&&d[u]+edges[e].cost<d[v]) { d[v]=d[u]+edges[e].cost; pre[v]=u;path[v]=e; q.push(v); } } } return (pre[t]==-1)?false:true; } int MinCostFlow(int s,int t) { int cost=0,flow=0; while(Spfa(s,t)) { int f=inf; for(int u=t;u!=s;u=pre[u]) { if(edges[path[u]].cap<f) f=edges[path[u]].cap; } flow+=f; cost+=d[t]*f; for(int u=t;u!=s;u=pre[u]) { edges[path[u]].cap-=f; edges[path[u]^1].cap+=f; } } return cost; } int main() { cnt=0;memset(head,-1,sizeof(head)); return 0; }
强连通分量(tarjan):
vector<int> G[maxn]; stack<int> S;
int pre[maxn],low[maxn],scc[maxn],scc_val[maxn]; int scc_cnt,dfs_clock; int n,m;void dfs(int u) { pre[u]=low[u]=++dfs_clock; int len=G[u].size();S.push(u); for(int i=0;i<len;i++) { int v=G[u][i]; if(!pre[v]) { dfs(v); low[u]=min(low[u],low[v]); } else if(!scc[v]) low[u]=min(low[u],pre[v]); } if(pre[u]==low[u]) { scc_cnt++;int cnt=0; for(;;) { int t=S.top();S.pop(); scc[t]=scc_cnt;cnt++; if(t==u) break; } scc_val[scc_cnt]=cnt; } } void find_scc() { memset(pre,0,sizeof(pre)); memset(low,0,sizeof(low)); memset(scc,0,sizeof(scc)); scc_cnt=0;dfs_clock=0; for(int i=1;i<=n;i++) { if(!pre[i]) dfs(i); } }
Dijkstra:
void dijkstra(int u,int n) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) dist[i]=G[u][i]; vis[u]=1; for(int i=1;i<n;i++) { int mind=inf,v=u; for(int j=1;j<=n;j++) { if((!vis[j])&&dist[j]<mind) { mind=dist[j];v=j; } } vis[v]=1; for(int j=1;j<=n;j++) { if(vis[j]) continue; if(dist[j]>mind+G[v][j]) { dist[j]=mind+G[v][j]; } } } }
最大团:
int G[maxn][maxn],n; int num[maxn]; int V[maxn][maxn],ans=0; bool dfs(int tot,int cnt) { if(tot==0) { if(cnt>ans) {ans=cnt;return true;} } for(int i=0;i<tot;i++) { if(cnt+(tot-i)<=ans) return false; if(cnt+num[V[cnt][i]]<=ans) return false; int k=0; for(int j=i+1;j<tot;j++) if(G[V[cnt][i]][V[cnt][j]]) V[cnt+1][k++]=V[cnt][j]; if(dfs(k,cnt+1)) return true; } return false; } void query_max() { ans=1; for(int i=n;i>0;i--) { int k=0; for(int j=i+1;j<=n;j++) { if(G[i][j]) V[1][k++]=j; } dfs(k,1); num[i]=ans; } }
数论:
中国剩余定理:
ll a[maxn],m[maxn]; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll ex_gcd(ll a,ll b,ll &x,ll &y) { if(b==0) {x=1;y=0;return a;} ll ans=ex_gcd(b,a%b,x,y); ll temp=x;x=y;y=temp-(a/b)*y; return ans; } ll Inv(ll a,ll b) { ll x,y,d; d=ex_gcd(a,b,x,y); return (d!=1)?-1:(x%b+b)%b; } bool Merge(ll a1,ll m1,ll a2,ll m2,ll &a3,ll &m3) { ll d=gcd(m1,m2),c=a2-a1; if(c%d) return false; c=(c%m2+m2)%m2; m1/=d;m2/=d;c/=d; c*=Inv(m1,m2); c%=m2;c*=m1*d;c+=a1; m3=m1*m2*d; a3=(c%m3+m3)%m3; return true; } ll CRT(int n) { ll a1=a[1],m1=m[1]; for(int i=2;i<=n;i++) { ll a2=a[i],m2=m[i],m3, a3; if(!Merge(a1,m1,a2,m2,a3,m3)) return -1; a1=a3;m1=m3; } return (a1%m1+m1)%m1; } /*ll CRT(int n) //m两两互素时 { ll M=1,ans=0; for(int i=1;i<=n;i++) M*=m[i]; for(int i=1;i<=n;i++) { ll x,y,Mi=M/m[i]; ex_gcd(Mi,m[i],x,y); ans=(ans+Mi*x*a[i])%M; } return (ans<0)?ans+M:ans; }*/
稳定婚姻问题:
int a[maxn][maxn],b[maxn][maxn],n; //a-->男生的期望 b-->女生的期望 //第二维从0开始 int ans[maxn]; //每位男生选中的女生 int manStartPos[maxn];//记录每位男生选取的是心目中第几位的女生 int ladyNow[maxn];//女生对应的男生 int GetPositionFromLady(int laday, int man) { for(int i=0;i<n;i++) if(b[laday][i]==man) return i; return -1; } void ChoosePartener(stack<int>& S, int manPos) { //选择自己名单上排在首位的女人 int perferLady = a[manPos][manStartPos[manPos]]; //如果该女孩没有接受过表白,则接受该男孩的表白 if(ladyNow[perferLady]==-1) { ladyNow[perferLady]=manPos; ans[manPos]=perferLady; } //如果已经有人向她表白,则判断其现在拥有的有没有现在追求的好 else { int oldPos=GetPositionFromLady(perferLady,ladyNow[perferLady]); int newPos=GetPositionFromLady(perferLady,manPos); if(oldPos<newPos) { manStartPos[manPos]++;//说明该女生更喜欢现在拥有的,选心目中第二位 //加入单身行列 S.push(manPos); } else //换男友 { //被甩的男友恢复自由身份 manStartPos[ladyNow[perferLady]]++; //加入单身行列 S.push(ladyNow[perferLady]); //将追求的男士改为现任男友 ladyNow[perferLady]=manPos; ans[manPos]=perferLady; } } } void solve() { memset(ladyNow,-1,sizeof(ladyNow)); memset(manStartPos,0,sizeof(manStartPos)); memset(ans,0,sizeof(ans)); stack<int> S; // 还处于单身的男士 //进行第一轮迭代,每个男生都选择自己名单上排在首位的女生。 for(int i=1;i<=n;i++) ChoosePartener(S,i); while(S.size()!=0) { int manPos=S.top();S.pop(); ChoosePartener(S,manPos); } }
高斯消元:
int var,equ; double a[250][250],x[250]; int Gauss() { for(int k=0,col=0;k<equ&&col<var;k++,col++) { int max_r=k; for(int i=k+1;i<equ;i++) if(fabs(a[i][col])>fabs(a[max_r][col])) max_r=i; if(fabs(a[max_r][col])<Eps) return 0; if(k!=max_r) { for(int j=col;j<var;j++) swap(a[k][j],a[max_r][j]); swap(x[k],x[max_r]); } x[k]/=a[k][col]; for(int j=col+1;j<var;j++) a[k][j]/=a[k][col]; a[k][col]=1; for(int i=0;i<equ;i++) if(i!=k) { x[i]-=x[k]*a[i][col]; for(int j=col+1;j<var;j++) a[i][j]-=a[k][j]*a[i][col]; a[i][col]=0; } } return 1; }
数位DP:
int a[20]; ll dp[20][state];//不同题目状态不同 ll dfs(int pos,/*state变量*/,bool lead/*前导零*/,bool limit/*数位上界变量*/)//不是每个题都要判断前导零 { if(pos==-1) return 1; if(!limit&&!lead&&dp[pos][state]!=-1) return dp[pos][state]; int up=limit?a[pos]:9; ll ans=0; for(int i=0;i<=up;i++) { if() ... else if()... ans+=dfs(pos-1,/*状态转移*/,lead && i==0,limit && i==a[pos]) /*这里还算比较灵活,不过做几个题就觉得这里也是套路了 大概就是说,我当前数位枚举的数是i,然后根据题目的约束条件分类讨论 去计算不同情况下的个数,还有要根据state变量来保证i的合法性,比如题目 要求数位上不能有62连续出现,那么就是state就是要保存前一位pre,然后分类, 前一位如果是6那么这意味就不能是2,这里一定要保存枚举的这个数是合法*/ } if(!limit&&!lead) dp[pos][state]=ans; return ans; }
ll solve(ll x) { int pos=0; while(x)//把数位都分解出来 { a[pos++]=x%10;//个人老是喜欢编号为[0,pos),看不惯的就按自己习惯来,反正注意数位边界就行 x/=10; } return dfs(pos-1,/*一系列状态 */,true,true); }
多项式类:
struct polynomial { int num[1200],len; polynomial() {mes(num,0);len=0;} polynomial(int *_num,int _len) {FOR(i,0,_len) num[i]=_num[i];_len=len;} ///先输入最高次项的指数,再依次(从低到高)输入每项的系数 void input() {scanfi(len);FOR(i,0,len) scanfi(num[i]);} void print(char v) { if(len<0) {printf("Error!!!!\n");return;} bool flag=false; for(int i=len;i>=1;i--) { if(num[i]==0) continue; if(num[i]>0) {if(flag) printf("+");}else if(num[i]==-1) printf("-"); abs(num[i])==1?true:printf("%d",num[i]);flag=true; printf("%c",v);if(i!=1) printf("^%d",i); } if(num[0]>0&&flag) printf("+"); if(num[0]!=0) printf("%d",num[0]);else if(!flag) printf("0"); } void print_endl(char v) {print(v);print_b;} polynomial operator + (polynomial a) { polynomial c;c.len=max(len,a.len); FOR(i,0,c.len) c.num[i]=num[i]+a.num[i]; while(c.len>0&&c.num[c.len]==0) c.len--;return c; } polynomial operator - (polynomial a) { polynomial c;c.len=max(len,a.len); FOR(i,0,c.len) c.num[i]=num[i]-a.num[i]; while(c.len>0&&c.num[c.len]==0) c.len--;return c; } polynomial operator * (int a) { polynomial c;c.len=len; FOR(i,0,len) c.num[i]=num[i]*a; while(c.len>0&&c.num[c.len]==0) c.len--;return c; } polynomial operator * (polynomial a) { polynomial c;c.len=len+a.len; FOR(i,0,len) FOR(j,0,a.len) c.num[i+j]+=num[i]*a.num[j]; while(c.len>0&&c.num[len]==0) c.len--;return c; } polynomial operator / (polynomial a) { polynomial c;c.len=len-a.len; if(c.len<0) return c; polynomial d=*this; for(int i=len;i>=a.len;i--) { if(d.num[i]%a.num[a.len]!=0) {c.len=-1;return c;} int t=d.num[i]/a.num[a.len]; if(t!=0) { FOR(j,0,a.len) d.num[i-j]-=a.num[a.len-j]*t; c.num[i-a.len]+=t; } } while(d.len>0&&d.num[len]==0) d.len--; if(d.len!=0) {c.len=-1;return c;} return c; } polynomial operator % (polynomial a) { polynomial c;c.len=len-a.len; if(c.len<0) return c; polynomial d=*this; for(int i=len;i>=a.len;i--) { if(d.num[i]%a.num[a.len]!=0) {c.len=-1;return c;} int t=d.num[i]/a.num[a.len]; if(t!=0) { FOR(j,0,a.len) d.num[i-j]-=a.num[a.len-j]*t; c.num[i-a.len]+=t; } } return d; } bool operator < (polynomial a) { if(len!=a.len) return len<a.len; for(int i=len;i>=0;i--) if(num[i]!=a.num[i]) { if(abs(num[i])!=abs(a.num[i])) return abs(num[i])<abs(a.num[i]); else return num[i]<0; } return false; } bool operator > (polynomial a) {return a<*this;} bool operator <= (polynomial a) {return !(*this>a);} bool operator >= (polynomial a) {return !(*this<a);} bool operator != (polynomial a) {return a<*this||*this<a;} bool operator == (polynomial a) {return !(a<*this)&&!(*this<a);} polynomial operator += (polynomial a) {return *this=*this+a;} polynomial operator -= (polynomial a) {return *this=*this-a;} polynomial operator *= (polynomial a) {return *this=*this*a;} polynomial operator /= (polynomial a) {return *this=*this/a;} polynomial operator %= (polynomial a) {return *this=*this%a;} };