Code Library 打印面
---
/*==============================================*\ | Code Library \*==============================================*/ /** head-file **/ #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstring> #include <string> #include <vector> #include <queue> #include <stack> #include <list> #include <set> #include <map> #include <algorithm> /** define-for **/ #define REP(i, n) for (int i=0;i<int(n);++i) #define FOR(i, a, b) for (int i=int(a);i<int(b);++i) #define DWN(i, b, a) for (int i=int(b-1);i>=int(a);--i) #define REP_1(i, n) for (int i=1;i<=int(n);++i) #define FOR_1(i, a, b) for (int i=int(a);i<=int(b);++i) #define DWN_1(i, b, a) for (int i=int(b);i>=int(a);--i) #define REP_N(i, n) for (i=0;i<int(n);++i) #define FOR_N(i, a, b) for (i=int(a);i<int(b);++i) #define DWN_N(i, b, a) for (i=int(b-1);i>=int(a);--i) #define REP_1_N(i, n) for (i=1;i<=int(n);++i) #define FOR_1_N(i, a, b) for (i=int(a);i<=int(b);++i) #define DWN_1_N(i, b, a) for (i=int(b);i>=int(a);--i) /** define-useful **/ #define clr(x,a) memset(x,a,sizeof(x)) #define sz(x) int(x.size()) #define see(x) cerr<<#x<<" "<<x<<endl #define se(x) cerr<<" "<<x #define pb push_back #define mp make_pair /** test **/ #define Display(A, n, m) { \ REP(i, n){ \ REP(j, m) cout << A[i][j] << " "; \ cout << endl; \ } \ } #define Display_1(A, n, m) { \ REP_1(i, n){ \ REP_1(j, m) cout << A[i][j] << " "; \ cout << endl; \ } \ } using namespace std; /** typedef **/ typedef long long LL; /** Add - On **/ const int direct4[4][2]={ {0,1},{1,0},{0,-1},{-1,0} }; const int direct8[8][2]={ {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} }; const int direct3[6][3]={ {1,0,0},{0,1,0},{0,0,1},{-1,0,0},{0,-1,0},{0,0,-1} }; const int MOD = 1000000007; const int INF = 0x3f3f3f3f; const long long INFF = 1LL << 60; const double EPS = 1e-9; const double OO = 1e15; const double PI = acos(-1.0); //M_PI; const int maxn=11111; const int maxm=1111111; int n,m; /*==============================================*\ | 建图 | INIT: init(int n):void | CALL: addedge(int u,int v,int c):void \*==============================================*/ struct EdgeNode{ int to; int w; int next; }; struct Graph{ int head[maxn]; EdgeNode edges[maxm]; int edge,n; void init(int n){ memset(head,-1,sizeof(head)); this->n=n; edge=0; } void addedge(int u,int v,int c){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } }; /*==============================================*\ | Dijkstra+堆优化 | INIT: init(n);addedge(u,v,c);节点编号0~n | CALL: dijkstra(int s);dis[]:最短路;pre[]:前驱 \*==============================================*/ struct HeapNode{ int d,u; HeapNode(){} HeapNode(int a,int b):d(a),u(b){} bool operator<(const HeapNode& rhs) const{ return d>rhs.d; } }; struct Dijkstra{ EdgeNode edges[maxm]; int head[maxn]; int edge,n; void init(int n){ this->n=n; memset(head,-1,sizeof(head)); edge=0; } void addedge(int u,int v,int c){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } bool done[maxn]; int dis[maxn]; int pre[maxn]; void dijkstra(int s){ priority_queue<HeapNode>que; for (int i=0;i<=n;i++) dis[i]=INF; dis[s]=0; memset(done,0,sizeof(done)); que.push(HeapNode(0,s)); while (!que.empty()){ HeapNode x=que.top(); que.pop(); int u=x.u; if (done[u]) continue; done[u]=true; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; int w=edges[i].w; if (dis[v]>dis[u]+w){ dis[v]=dis[u]+w; pre[v]=u; que.push(HeapNode(dis[v],v)); } } } } }; /*==============================================*\ | BellmanFord+队列优化 | INIT: init(n);addedge(u,v,c);节点编号0~n | CALL: spfa(int s):bool;dist[]:最短路 \*==============================================*/ struct BellmanFord{ EdgeNode edges[maxm]; int head[maxn],edge,n; bool vis[maxn]; int outque[maxn]; queue<int>que; int dis[maxn]; void addedge(int u,int v,int c){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } void init(int n){ memset(head,-1,sizeof(head)); edge=0; this->n=n; } bool spfa(int s){ int u; for (int i=0;i<=n;i++) dis[i]=INF; memset(vis,0,sizeof(vis)); memset(outque,0,sizeof(outque)); while (!que.empty()) que.pop(); que.push(s); vis[s]=true; dis[s]=0; while (!que.empty()){ u=que.front(); que.pop(); vis[u]=false; outque[u]++; if (outque[u]>n) return false; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; int w=edges[i].w; if (dis[v]==INF||dis[v]>dis[u]+w){ dis[v]=dis[u]+w; if (!vis[v]){ vis[v]=true; que.push(v); } } } } return true; } }; /*==============================================*\ | 强连通分量-Tarjan | INIT: init(n);addedge(u,v);节点编号0~n-1 | CALL: find_scc();sccno[x]:节点x所属强连通分量 \*==============================================*/ struct Tarjan{ int head[maxn]; EdgeNode edges[maxm]; int edge,n; void init(int n){ memset(head,-1,sizeof(head)); this->n=n; edge=0; } void addedge(int u,int v,int c=0){ edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } int pre[maxn],lowlink[maxn],sccno[maxn],scc_cnt,dfs_clock; stack<int>stk; void dfs(int u){ pre[u]=lowlink[u]=++dfs_clock; stk.push(u); for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if (!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if (lowlink[u]==pre[u]){ scc_cnt++; int x; do{ x=stk.top(); stk.pop(); sccno[x]=scc_cnt; }while (x!=u); } } void find_scc(){ dfs_clock=scc_cnt=0; memset(sccno,0,sizeof(sccno)); memset(pre,0,sizeof(pre)); while (!stk.empty()) stk.pop(); for (int i=0;i<n;i++) if (!pre[i]) dfs(i); } }; /*==============================================*\ | 点双连通/割点/桥/边双连通 | INIT: init(n);addedge(u,v);无向图;节点编号1~n | CALL: find_bcc():点双连通/割点/桥 | find_block():边双连通,先要求出桥 | iscut[]:割点;EdgeNode_1.cut:桥 | vector<int>bcc[x]:双连通分量x所包含的节点 | bccno[x]:节点x所属的点双连通分量,割点的值无意义 | block[x]:节点x所属的边双连通分量 \*==============================================*/ struct EdgeNode_1{ int to; int w; int next; bool cut; }; struct Edge{ int u; int v; Edge(){} Edge(int a,int b):u(a),v(b){} }; struct Bcc_Graph{ int head[maxn]; EdgeNode_1 edges[maxm]; int edge,n; void init(int n){ memset(head,-1,sizeof(head)); this->n=n; edge=0; } void addedge(int u,int v,int c=0){ edges[edge].cut=0,edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } //点双连通/割点/桥 int dfn[maxn],low[maxn],bccno[maxn],dfs_clock,bcc_cnt; bool iscut[maxn]; vector<int>bcc[maxn]; stack<Edge>stk; int dfs(int u,int fa){ int lowu=dfn[u]=++dfs_clock; int child=0; for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (v==fa) continue; Edge e=Edge(u,v); if (!dfn[v]){ stk.push(e); child++; int lowv=dfs(v,u); lowu=min(lowu,lowv); if (dfn[u]<=lowv){ iscut[u]=true;//割点 //BEGIN 求点双连通分量 bcc_cnt++; bcc[bcc_cnt].clear(); Edge x; do{ x=stk.top(); stk.pop(); if (bccno[x.u]!=bcc_cnt){ bcc[bcc_cnt].push_back(x.u); bccno[x.u]=bcc_cnt; } if (bccno[x.v]!=bcc_cnt){ bcc[bcc_cnt].push_back(x.v); bccno[x.v]=bcc_cnt; } }while (x.u!=u||x.v!=v); //END } if (dfn[u]<lowv){//cut 桥 edges[i].cut=true; edges[i^1].cut=true; } } else if (dfn[v]<dfn[u]){ stk.push(e);//BEGIN-END 点双连通 lowu=min(lowu,dfn[v]); } } if (fa<0&&child==1) iscut[u]=0;//割点 low[u]=lowu; return lowu; } void find_bcc(){ while (!stk.empty()) stk.pop(); memset(dfn,0,sizeof(dfn)); memset(iscut,0,sizeof(iscut)); memset(bccno,0,sizeof(bccno)); dfs_clock=bcc_cnt=0; for (int i=1;i<=n;i++){ if (!dfn[i]) dfs(i,-1); } } //边双连通分量 int block[maxn]; int vis[maxn]; int b_num; void b_dfs(int u){ vis[u]=true; block[u]=b_num; for (int i=head[u];i!=-1;i=edges[i].next) { if (edges[i].cut) continue; int v=edges[i].to; if (!vis[v]) b_dfs(v); } } void find_block(){ memset(block,0,sizeof(block)); memset(vis,0,sizeof(vis)); b_num=0; for (int i=1;i<=n;i++){ if (!vis[i]){ b_num++; b_dfs(i); } } } }; /*==============================================*\ | TwoSAT | INIT: init(n);addedge(u,v);节点编号0~n-1 | CALL: add_clause(x,xval,y,yval) x=xval or y=yval | add_con(x,xval) x=xval | solve():bool;mark[i]:选取i \*==============================================*/ struct TwoSAT{ int head[maxn*2]; EdgeNode edges[maxm*2]; int edge,n; bool mark[maxn*2]; int S[maxn*2],c; void init(int n){ this->n=n; memset(mark,0,sizeof(mark)); memset(head,-1,sizeof(head)); edge=0; } void addedge(int u,int v){ edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } // x = xval or y = yval void add_clause(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; addedge(x^1,y); addedge(y^1,x); } // x = xval void add_con(int x,int xval){ x=x*2+xval; addedge(x^1,x); } bool dfs(int x){ if (mark[x^1]) return false; if (mark[x]) return true; mark[x]=true; S[c++]=x; for (int i=head[x];i!=-1;i=edges[i].next) if (!dfs(edges[i].to)) return false; return true; } bool solve(){ for (int i=0;i<n*2;i+=2) if (!mark[i]&&!mark[i+1]){ c=0; if (!dfs(i)){ while (c>0) mark[S[--c]]=false; if (!dfs(i+1)) return false; } } return true; } }; /*==============================================*\ | TwoSAT-Tarjan强连通 | INIT: init(n),addedge(u,v),节点0~n-1 | CALL: add_self(x,xval,y,yval) x!=xval->y=yval | solve():bool \*==============================================*/ struct TWOSAT{ int head[maxn*2]; EdgeNode edges[maxm*2]; int edge,n; void init(int n){ this->n=2*n; memset(head,-1,sizeof(head)); edge=0; } void addedge(int u,int v){ edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; } // x = xval or y = yval void add_clause(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; addedge(x^1,y); addedge(y^1,x); } //x=xval void add_con(int x,int xval){ x=x*2+xval; addedge(x^1,x); } //x!=xval->y=yval void add_self(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; addedge(x,y); } int pre[maxn],lowlink[maxn],sccno[maxn],scc_cnt,dfs_clock; stack<int>stk; void dfs(int u){ pre[u]=lowlink[u]=++dfs_clock; stk.push(u); for (int i=head[u];i!=-1;i=edges[i].next){ int v=edges[i].to; if (!pre[v]){ dfs(v); lowlink[u]=min(lowlink[u],lowlink[v]); } else if (!sccno[v]){ lowlink[u]=min(lowlink[u],pre[v]); } } if (lowlink[u]==pre[u]){ scc_cnt++; int x; do{ x=stk.top(); stk.pop(); sccno[x]=scc_cnt; }while (x!=u); } } void find_scc(int n){ dfs_clock=scc_cnt=0; memset(sccno,0,sizeof(sccno)); memset(pre,0,sizeof(pre)); while (!stk.empty()) stk.pop(); for (int i=0;i<n;i++) if (!pre[i]) dfs(i); } bool solve(){ find_scc(n); for (int i=0;i<n;i+=2){ if (sccno[i]==sccno[i^1]) return false; } return true; } }; /*==============================================*\ | Dinic最大流 | INIT: prepare(n,S,T);addedge(u,v,c);节点0~n | CALL: Dinic_flow():int \*==============================================*/ struct edgenode{ int to,flow,next; }; struct Dinic{ int node,src,dest,edge; int head[maxn],work[maxn],dis[maxn],q[maxn]; edgenode edges[maxm]; void prepare(int _node,int _src,int _dest){ node=_node,src=_src,dest=_dest; memset(head,-1,sizeof(head)); edge=0; } void addedge(int u,int v,int c){ edges[edge].flow=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++; edges[edge].flow=0,edges[edge].to=u,edges[edge].next=head[v],head[v]=edge++; } bool Dinic_bfs(){ int i,u,v,l,r=0; for (i=0; i<node; i++) dis[i]=-1; dis[q[r++]=src]=0; for (l=0; l<r; l++){ for (i=head[u=q[l]]; i!=-1; i=edges[i].next){ if (edges[i].flow&&dis[v=edges[i].to]<0){ dis[q[r++]=v]=dis[u]+1; if (v==dest) return true; } } } return false; } int Dinic_dfs(int u,int exp){ if (u==dest) return exp; for (int &i=work[u],v,tmp; i!=-1; i=edges[i].next){ if (edges[i].flow&&dis[v=edges[i].to]==dis[u]+1&& (tmp=Dinic_dfs(v,min(exp,edges[i].flow)))>0){ edges[i].flow-=tmp; edges[i^1].flow+=tmp; return tmp; } } return 0; } int Dinic_flow(){ int i,ret=0,delta; while (Dinic_bfs()){ for (i=0;i<node;i++) work[i]=head[i]; while (delta=Dinic_dfs(src,INF)) ret+=delta; } return ret; } }; /*==============================================*\ | 最小费用最大流 | INIT: prepare(n,S,T);addedge(u,v,f,c);编号0~n-1 | CALL: spfaflow():int \*==============================================*/ struct edgenode_1{ int to;//边的指向 int flow;//边的容量 int cost;//边的费用 int next;//链表的下一条边 }; struct MinCost{ edgenode_1 edges[maxm]; int node,src,dest,edge;//node节点数,src源点,dest汇点,edge边数 int head[maxn],p[maxn],dis[maxn],q[maxn],vis[maxn]; //head链表头,p记录可行流上节点对应的反向边,dis计算距离 void prepare(int _node=0,int _src=0,int _dest=0){ node=_node,src=_src,dest=_dest; memset(head,-1,sizeof(head)); memset(vis,0,sizeof(vis)); edge=0; } void addedge(int u,int v,int f,int c){ edges[edge].flow=f;edges[edge].cost=c;edges[edge].to=v; edges[edge].next=head[u];head[u]=edge++; edges[edge].flow=0;edges[edge].cost=-c;edges[edge].to=u; edges[edge].next=head[v];head[v]=edge++; } bool spfa(){ int i,u,v,l,r=0,tmp; for (i=0;i<node;i++) dis[i]=INF; dis[q[r++]=src]=0; p[src]=p[dest]=-1; for (l=0;l!=r;((++l>=maxn)?l=0:l)){ for (i=head[u=q[l]],vis[u]=false;i!=-1;i=edges[i].next){ if (edges[i].flow&&dis[v=edges[i].to]>(tmp=dis[u]+edges[i].cost)){ dis[v]=tmp; p[v]=i^1; if (vis[v]) continue; vis[q[r++]=v]=true; if (r>=maxn) r=0; } } } return p[dest]>=0; } int spfaflow(){ int i,ret=0,delta; while (spfa()){//按记录原路返回求流量 for (i=p[dest],delta=INF;i>=0;i=p[edges[i].to]){ delta=min(delta,edges[i^1].flow); } for (int i=p[dest];i>=0;i=p[edges[i].to]){ edges[i].flow+=delta; edges[i^1].flow-=delta; } ret+=delta*dis[dest]; } return ret; } };
---
---
/*==============================================*\ | 最大公约数-辗转相除 \*==============================================*/ int gcd(int a,int b){ if (b==0) return a; return gcd(b,a%b); } /*==============================================*\ | 扩展欧几里得 | ax+by=gcd(a,b) \*==============================================*/ int extgcd(int a,int b,int& x,int& y){ int d=a; if (b!=0){ d=extgcd(b,a%b,y,x); y-=(a/b)*x; }else{ x=1;y=0; } return d; } /*==============================================*\ | 素数-埃氏筛法 \*==============================================*/ int prime[maxn]; bool is_prime[maxn+1]; int sieve(int n){ int p=0; for (int i=0;i<=n;i++) is_prime[i]=true; is_prime[0]=is_prime[1]=false; for (int i=2;i<=n;i++){ if (is_prime[i]){ prime[p++]=i; for (int j=2*i;j<=n;j+=i) is_prime[j]=false; } } return p; } /*==============================================*\ | 快速幂 \*==============================================*/ LL modPow(LL x,LL n,LL mod){ if (n==0) return 1; LL res=modPow(x*x%mod,n/2,mod); if (n&1) res=res*x%mod; return res; } /*==============================================*\ | 高斯消元-列主元 | 求解Ax=b,A为矩阵 无解/多解时返回空数组 \*==============================================*/ const double eps=1e-8; typedef vector<double>vec; typedef vector<vec>mat; vec gaussJordan(const mat& A,const vec& b){ int n=A.size(); mat B(n,vec(n+1)); for (int i=0;i<n;i++) for (int j=0;j<n;j++) B[i][j]=A[i][j]; for (int i=0;i<n;i++) B[i][n]=b[i]; for (int i=0;i<n;i++){ int pivot=i; for (int j=i;j<n;j++){ if (abs(B[j][i])>abs(B[pivot][i])) pivot=j; } swap(B[i],B[pivot]); if (abs(B[i][i]<eps)) return vec();//无解或多解 for (int j=i+1;j<=n;j++) B[i][j]/=B[i][i]; for (int j=0;j<n;j++){ if (i!=j){ for (int k=i+1;k<=n;k++) B[j][k]-=B[j][i]*B[i][k]; } } } vec x(n); for (int i=0;i<n;i++) x[i]=B[i][n]; return x; } /*==============================================*\ | 逆元 | ax≡b(mod m) x=a逆×b | gcd(a,m)!=1逆元不存在 \*==============================================*/ int modInverse(int a,int m){ int x,y; extgcd(a,m,x,y); return (m+x%m)%m; }
---
/*==============================================*\ | 矩阵快速幂 \*==============================================*/ const int M=10000; typedef vector<int>vec; typedef vector<vec>mat; mat mul(mat &A,mat &B){ mat C(A.size(),vec(B[0].size())); for (int i=0;i<(int)A.size();i++){ for (int k=0;k<(int)B.size();k++){ for (int j=0;j<(int)B[0].size();j++){ C[i][j]=(C[i][j]+A[i][k]*B[k][j])%M; } } } return C; } mat pow(mat A,LL n){ mat B(A.size(),vec(A.size())); for (int i=0;i<(int)A.size();i++){ B[i][i]=1; } while (n>0){ if (n&1) B=mul(B,A); A=mul(A,A); n>>=1; } return B; }
---