沙雕的gcd:
//1.gcd int gcd(int a,int b) { return b?gcd(b,a%b):a; }
还有个exgcd:
//2.扩展gcd )extend great common divisor ll exgcd(ll l,ll r,ll &x,ll &y) { if(r==0) { x=1; y=0; return l; } else { ll d=exgcd(r,l%r,y,x); y-=l/r*x; return d; } }
求逆元:
//3.求a关于m的乘法逆元 ll mod_inverse(ll a,ll m) { ll x,y; if(exgcd(a,m,x,y)==1)//ax+my=1 return (x%m+m)%m; return -1;//不存在 }
快速幂:
//4.快速幂quick power ll qpow(ll a,ll b,ll m) { ll ans=1; ll k=a; while(b) { if(b&1)ans=ans*k%m; k=k*k%m; b>>=1; } return ans; }
快速乘(也叫二分乘法):
//5.快速乘,直接乘会爆ll时需要它,也叫二分乘法。 ll qmul(ll a,ll b,ll m) { ll ans=0; ll k=a; ll f=1;//f是用来存负号的 if(k<0) { f=-1; k=-k; } if(b<0) { f*=-1; b=-b; } while(b) { if(b&1) ans=(ans+k)%m; k=(k+k)%m; b>>=1; } return ans*f; }
中国剩余定理:
//6.中国剩余定理CRT (x=ai mod mi) ll china(ll n, ll *a,ll *m) { ll M=1,y,x=0,d; for(ll i = 1; i <= n; i++) M *= m[i]; for(ll i = 1; i <= n; i++) { ll w = M /m[i]; exgcd(m[i], w, d, y);//m[i]*d+w*y=1 x = (x + y*w*a[i]) % M; } return (x+M)%M; }
筛素数:
//7.筛素数,全局:int cnt,prime[N],p[N]; void isprime() { cnt = 0; memset(prime,true,sizeof(prime)); for(int i=2; i) { if(prime[i]) { p[cnt++] = i; for(int j=i+i; j i) prime[j] = false; } } }
快速计算逆元:
//8.快速计算逆元 //补充:>>关于快速算逆元的递推式的证明<< void inverse() { inv[1] = 1; for(int i=2; i) { if(i >= M) break; inv[i] = (M-M/i)*inv[M%i]%M; } }
组合数取模:
//9.组合数取模 n和m 10^5时,预处理出逆元和阶乘 ll fac[N]= {1,1},inv[N]= {1,1},f[N]= {1,1}; ll C(ll a,ll b) { if(b>a)return 0; return fac[a]*inv[b]%M*inv[a-b]%M; } void init() { //快速计算阶乘的逆元 for(int i=2; i) { fac[i]=fac[i-1]*i%M; f[i]=(M-M/i)*f[M%i]%M; inv[i]=inv[i-1]*f[i]%M; } } n较大10^9,但是m较小10^5时, ll C(ll n,ll m) { if(m>n)return 0; ll ans=1; for(int i=1; i<=m; i++) ans=ans*(n-i+1)%M*qpow(i,M-2,M)%M; return ans; } //n和m特别大10^18时但是p较小10^5时用lucas
Lucas大组合取模:
//10.Lucas大组合取模 #define N 100005 #define M 100007 ll n,m,fac[N]= {1}; ll C(ll n,ll m) { if(m>n)return 0; return fac[n]*qpow(fac[m],M-2,M)%M*qpow(fac[n-m],M-2,M)%M;//费马小定理求逆元 } ll lucas(ll n,ll m) { if(!m)return 1; return(C(n%M,m%M)*lucas(n/M,m/M))%M; } void init() { for(int i=1; i<=M; i++) fac[i]=fac[i-1]*i%M; }
质因数分解:
//11.质因数分解 cin>>n; for(int i=2; i<=n; i++) { if(n==0)break; while(n%i==0) { n/=i; k[++ans]=i; } }
试除法:
//12.试除法 bool check(int n) { if(n==1)return false; for(int i=2; i<=sqrt(n); ++i) if(n%i==0)return false; return true; }
miller-rabin算法:
//13.miller-rabin算法 int test[10]= {2,3,5,7,11,13,19,23}; int qpow(int a,int b,int p) { int ans=1; while(b) { if(b&1)ans=1ll*ans*a%p; a=1ll*a*a%p,b>>=1; } return ans; } bool miller_rabin(int p) { if(p==1)return 0; int t=p-1; k=0; while(!(t&1))k++,t>>=1; for(int i=0; i<8; ++i) { if(p==test[i])return 1; long long a=qpow(test[i],t,p,),nx=a; for(int j=1; j<=k; ++j) { nx=(a*a)%p; if(nx==1&&a!=1&&a!=p-1) return 0; a-nx; } if(a!=1)return 0; } return 1; }
快读:
//14.快读 inline int read() { int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')w=-1; ch=getchar(); } while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar(); return s*w; }
spfa_dfs:
//15.spfa_dfs int spfa_dfs(int u) { vis[u]=1; for(int k=f[u]; k!=0; k=e[k].next) { int v=e[k].v,w=e[k].w; if( d[u]+w < d[v] ) { d[v]=d[u]+w; if(!vis[v]) { if(spfa_dfs(v)) return 1; } else return 1; } } vis[u]=0; return 0; }
spfa_dfs:
//16、spfa_bfs int spfa_bfs(int s) { queue <int> q; memset(d,0x3f,sizeof(d)); d[s]=0; memset(c,0,sizeof(c)); memset(vis,0,sizeof(vis)); q.push(s); vis[s]=1; c[s]=1; //顶点入队vis要做标记,另外要统计顶点的入队次数 int OK=1; while(!q.empty()) { int x; x=q.front(); q.pop(); vis[x]=0; //队头元素出队,并且消除标记 for(int k=f[x]; k!=0; k=nnext[k]) { //遍历顶点x的邻接表 int y=v[k]; if( d[x]+w[k] < d[y]) { d[y]=d[x]+w[k]; //松弛 if(!vis[y]) { //顶点y不在队内 vis[y]=1; //标记 c[y]++; //统计次数 q.push(y); //入队 if(c[y]>NN) //超过入队次数上限,说明有负环 return OK=0; } } } } return OK; }
欧拉函数:
1 for(i=1; i<=maxn; i++) 2 p[i]=i; 3 for(i=2; i<=maxn; i+=2) 4 p[i]/=2; 5 for(i=3; i<=maxn; i+=2) 6 if(p[i]==i) 7 { 8 for(j=i; j<=maxn; j+=i) 9 p[j]=p[j]/i*(i-1); 10 }
杂:
//cin,优化 cin.tie(0); ios_base::sync_with_stdio(false); //输出优化: void print( int k ) { num = 0; while( k > 0 ) ch[++num] = k % 10, k /= 10; while( num ) putchar( ch[num--]+48 ); putchar( 32 ); }
RMQ:
//区间查询最值问题 //预处理 void rmq_init() { for(int i=1; i<=N; i++) dp[i][0]=arr[i];//初始化 for(int j=1; (1<) for(int i=1; i+(1< 1<=N; i++) dp[i][j]=min(dp[i][j-1],dp[i+(1< 1)][j-1]); } //查询 int rmq(int l,int r) { int k=log2(r-l+1); return min(dp[l][k],dp[r-(1< 1][k]); }
RMQ转LCA:
int euler[MAXN*2]; int dep[MAXN*2]; int pos[MAXN]; int top; int rmq[MAXN*2][16]; void dfs(int u,int depth,int fa) { euler[++top]=u; dep[top]=depth; pos[u]=top; INE(i,u,e) { int v=e[i].v; if(v==fa) continue; dfs(v,depth+1,u); euler[++top]=u; dep[top]=depth; } } void RMQinit() { rep(i,1,top) rmq[i][0]=i; rep(j,1,16) rep(i,1,top) if(i+(1<1<=top) { if(dep[rmq[i][j-1]] 1< 1)][j-1]]) rmq[i][j]=rmq[i][j-1]; else rmq[i][j]=rmq[i+(1< 1)][j-1]; } } int RMQ(int l,int r) { int len=r-l+1; int LOG=0; for(;1< 1<=len;LOG++); if(dep[rmq[l][LOG]] 1< 1][LOG]]) return rmq[l][LOG]; else return rmq[r-(1< 1][LOG]; } void LCAinit() { dfs(1,0,-1); RMQinit(); } int LCA(int u,int v) { if(pos[u]>pos[v]) swap(u,v); return euler[RMQ(pos[u],pos[v])]; }
tarjan求LCA:
//并查集记录父亲的数组. int father[MAXN]; //并查集的查找函数,有路径压缩功能. int find ( int x ) { return father[x] == x ? x : father[x] = find ( father[x]); } //采用邻接表存储 struct { int v,next,lca,u; } e[2][MAXN<<2]; //分别记录边对和查询数对 int head[2][MAXN]; int cc; //添加边,flag表示模式 void add ( int flag , int u , int v ) { e[flag][cc].u = u; e[flag][cc].v = v; e[flag][cc].next = head[flag][u]; head[flag][u] = cc++; } //标记当前点是否访问过 bool visited[MAXN]; void LCA ( int u ) { father[u] = u; visited[u] = true; //深度优先搜索整棵树 for ( int i = head[0][u]; i != -1 ; i = e[0][i].next ) { int v = e[0][i].v; if ( visited[v] ) continue; LCA ( v ); //从叶节点开始,逐层标记父节点 father[v] = u; } //当前子树已经维护,利用并查集找到当前子树的查询数对的LCA for ( int i = head[1][u]; i != -1 ; i = e[1][i].next ) { int v = e[1][i].v; if ( !visited[v] ) continue; //如果当前u,v都已经访问过,那么一定维护过的子树中 e[1][i].lca = e[1][i^1].lca = find ( v ); } }
倍增求LCA:
#includeusing namespace std; struct node { int t,nex; } e[500001<<1]; int depht[500001],father[500001][22],lg[500001],head[500001]; int tot; inline void add(int x,int y) { e[++tot].t=y; e[tot].nex=head[x]; head[x]=tot; } inline void dfs(int now,int fath) { depht[now]=depht[fath]+1; father[now][0]=fath; for(register int i=1; (1<i) father[now][i]=father[father[now][i-1]][i-1]; for(register int i=head[now]; i; i=e[i].nex) { if(e[i].t!=fath)dfs(e[i].t,now); } } inline int lca(int x,int y) { if(depht[x]<depht[y]) swap(x,y); while(depht[x]>depht[y]) x=father[x][lg[depht[x]-depht[y]]-1]; if(x==y) return x; for(register int k=lg[depht[x]]; k>=0; --k) if(father[x][k]!=father[y][k]) x=father[x][k],y=father[y][k]; return father[x][0]; } int n,m,s; int main() { scanf("%d%d%d",&n,&m,&s); for(register int i=1; i<=n-1; ++i) { int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(s,0); for(register int i=1; i<=n; ++i) lg[i]=lg[i-1]+(1< 1]==i); for(register int i=1; i<=m; ++i) { int x,y; scanf("%d%d",&x,&y); printf("%d\n",lca(x,y)); } return 0; }
#includeusing namespace std; #define INF 0x3f3f3f3f #define MAXN 1000010 #define MAXM 5010 inline int read() { int x = 0,ff = 1;char ch = getchar(); while(!isdigit(ch)) { if(ch == '-') ff = -1; ch = getchar(); } while(isdigit(ch)) { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); } return x * ff; } inline void write(int x) { if(x < 0) putchar('-'),x = -x; if(x > 9) write(x / 10); putchar(x % 10 + '0'); } int a,ti = 0,cnt = 0,fa[MAXN],vis[MAXN],loop[MAXN]; int lin[MAXN],tot = 0; struct edge { int y,v,next; }e[MAXN]; inline void add(int xx,int yy,int vv) { e[++tot].y = yy; e[tot].v = vv; e[tot].next = lin[xx]; lin[xx] = tot; } void get_loop(int x) { vis[x] = ++ti; for(int i = lin[x],y;i;i = e[i].next) { if((y = e[i].y) == fa[x]) continue; if(vis[y]) { if(vis[y] < vis[x]) continue; loop[++cnt] = y; for(y = fa[y];y != fa[x];y = fa[y]) loop[++cnt] = y; } else fa[y] = x,get_loop(y); } } int main() { a = read(); for(int i = 1;i <= a;++i) { int y,v; y = read(); v = read(); add(i,y,v); add(y,i,v); } get_loop(1); for(int i = 1;i <= cnt;++i) write(loop[i]),putchar(' '); return 0; }
//18.tarjan void Tarjan ( int x ) { dfn[ x ] = ++dfs_num ; low[ x ] = dfs_num ; vis [ x ] = true ;//是否在栈中 stack [ ++top ] = x ; for ( int i=head[ x ] ; i!=0 ; i=e[i].next ) { int temp = e[ i ].to ; if ( !dfn[ temp ] ) { Tarjan ( temp ) ; low[ x ] = gmin ( low[ x ] , low[ temp ] ) ; } else if ( vis[ temp ])low[ x ] = gmin ( low[ x ] , dfn[ temp ] ) ; } if ( dfn[ x ]==low[ x ] ) {//构成强连通分量 vis[ x ] = false ; color[ x ] = ++col_num ;//染色 while ( stack[ top ] != x ) {//清空 color [stack[ top ]] = col_num ; vis [ stack[ top-- ] ] = false ; } top -- ; } }
#include#define MAXN 501 const int Big_B = 10; const int Big_L = 1; inline int intcmp_ (int a, int b) { if (a > b) return 1; return a < b ? -1 : 0; } struct Int { #define rg register inline int max (int a, int b) { return a > b ? a : b; } inline int min (int a, int b) { return a < b ? a : b; } std :: vector <int> c; Int () {} typedef long long LL; Int (int x) { for (; x > 0; c.push_back (x % Big_B), x /= Big_B); } Int (LL x) { for (; x > 0; c.push_back (x % Big_B), x /= Big_B); } inline void CrZ () { for (; !c.empty () && c.back () == 0; c.pop_back ()); } inline Int &operator += (const Int &rhs){ c.resize (max (c.size (), rhs.c.size ())); rg int i, t = 0, S; for (i = 0, S = rhs.c.size (); i < S; ++ i) c[i] += rhs.c[i] + t, t = c[i] >= Big_B, c[i] -= Big_B & (-t); for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i) c[i] += t, t = c[i] >= Big_B, c[i] -= Big_B & (-t); if (t) c.push_back (t); return *this; } inline Int &operator -= (const Int &rhs){ c.resize (max (c.size (), rhs.c.size ())); rg int i, t = 0, S; for (i = 0, S = rhs.c.size (); i < S; ++ i) c[i] -= rhs.c[i] + t, t = c[i] < 0, c[i] += Big_B & (-t); for (i = rhs.c.size (), S = c.size (); t && i < S; ++ i) c[i] -= t, t = c[i] < 0, c[i] += Big_B & (-t); CrZ (); return *this; } inline Int &operator *= (const Int &rhs){ rg int na = c.size (), i, j, S, ai; c.resize (na + rhs.c.size ()); LL t; for (i = na - 1; i >= 0; -- i){ ai = c[i], t = 0, c[i] = 0; for (j = 0, S = rhs.c.size (); j < S; ++ j){ t += c[i + j] + (LL) ai * rhs.c[j]; c[i + j] = t % Big_B, t /= Big_B; } for (j = rhs.c.size (), S = c.size (); t != 0 && i + j < S; ++ j) t += c[i + j], c[i + j] = t % Big_B, t /= Big_B; assert (t == 0); } CrZ (); return *this; } inline Int &operator /= (const Int &rhs) { return *this = div (rhs); } inline Int &operator %= (const Int &rhs) { return div (rhs), *this; } inline Int &shlb (int l = 1){ if (c.empty ()) return *this; c.resize (c.size () + l);rg int i; for (i = c.size () - 1; i >= l; -- i) c[i] = c[i - l]; for (i = 0; i < l; ++ i) c[i] = 0; return *this; } inline Int &shrb (int l = 1){ for (rg int i = 0; i < c.size () - l; ++ i) c[i] = c[i + l]; c.resize (max (c.size () - l, 0)); return *this; } inline Int div (const Int &rhs){ assert (!rhs.c.empty ()); Int q, r; rg int i; if (rhs > *this) return 0; q.c.resize (c.size () - rhs.c.size () + 1); rg int _l, _r, mid; for (i = c.size () - 1; i > c.size () - rhs.c.size (); -- i) r.shlb (), r += c[i]; for (i = c.size () - rhs.c.size (); i >= 0; -- i){ r.shlb (); r += c[i]; if (r.Comp (rhs) < 0) q.c[i] = 0; else { _l = 0, _r = Big_B; for (; _l != _r; ){ mid = _l + _r >> 1; if ((rhs * mid).Comp (r) <= 0) _l = mid + 1; else _r = mid; } q.c[i] = _l - 1, r -= rhs * q.c[i]; } } q.CrZ (), *this = r; return q; } inline int Comp (const Int &rhs) const { if (c.size () != rhs.c.size ()) return intcmp_ (c.size (), rhs.c.size ()); for (rg int i = c.size () - 1; i >= 0; -- i) if (c[i] != rhs.c[i]) return intcmp_ (c[i], rhs.c[i]); return 0; } friend inline Int operator + (const Int &lhs, const Int &rhs) { Int res = lhs; return res += rhs; } inline friend Int operator - (const Int &lhs, const Int &rhs){ if (lhs < rhs){ putchar ('-'); Int res = rhs; return res -= lhs; } else { Int res = lhs; return res -= rhs; } } friend inline Int operator * (const Int &lhs, const Int &rhs) { Int res = lhs; return res *= rhs; } friend inline Int operator / (const Int &lhs, const Int &rhs) { Int res = lhs; return res.div (rhs); } friend inline Int operator % (const Int &lhs, const Int &rhs) { Int res = lhs; return res.div (rhs), res; } friend inline std :: ostream &operator << (std :: ostream &out, const Int &rhs){ if (rhs.c.size () == 0) out << "0"; else { out << rhs.c.back (); for (rg int i = rhs.c.size () - 2; i >= 0; -- i) out << std :: setfill ('0') << std :: setw (Big_L) << rhs.c[i]; } return out; } friend inline std :: istream &operator >> (std :: istream &in, Int &rhs){ static char s[100000]; in >> s + 1; int Len = strlen (s + 1); int v = 0; LL r = 0, p = 1; for (rg int i = Len; i >= 1; -- i){ ++ v; r = r + (s[i] - '0') * p, p *= 10; if (v == Big_L) rhs.c.push_back (r), r = 0, v = 0, p = 1; } if (v != 0) rhs.c.push_back (r); return in; } friend inline bool operator < (const Int &lhs, const Int &rhs) { return lhs.Comp (rhs) < 0; } friend inline bool operator <= (const Int &lhs, const Int &rhs) { return lhs.Comp (rhs) <= 0; } friend inline bool operator > (const Int &lhs, const Int &rhs) { return lhs.Comp (rhs) > 0; } friend inline bool operator >= (const Int &lhs, const Int &rhs) { return lhs.Comp (rhs) >= 0; } friend inline bool operator == (const Int &lhs, const Int &rhs) { return lhs.Comp (rhs) == 0; } friend inline bool operator != (const Int &lhs, const Int &rhs) { return lhs.Comp (rhs) != 0; } #undef rg }; int Main (){ return 0; } int ZlycerQan = Main (); int main (int argc, char *argv[]) {;}
queue<int>q; vector<int>edge[n]; for(int i=0;i//n 节点的总数 if(in[i]==0) q.push(i); //将入度为0的点入队列 vector<int>ans; //ans 为拓扑序列 while(!q.empty()) { int p=q.front(); q.pop(); // 选一个入度为0的点,出队列 ans.push_back(p); for(int i=0;i ) { int y=edge[p][i]; in[y]--; if(in[y]==0) q.push(y); } } if(ans.size()==n) { for(int i=0;i ) printf( "%d ",ans[i] ); printf("\n"); } else printf("No Answer!\n");
有关最短路的东西:
//一、多源最短路算法——Floyd 算法 //floyd 算法主要用于求任意两点间的最短路径,也称最短最短路径问题 //核心代码: void floyd() { int i, j, k; for (k = 1; k <= n; ++k) //遍历所有的中间点 for (i = 1; i <= n; ++i) //遍历所有的起点 for (j = 1; j <= n; ++j) //遍历所有的终点 if (e[i][j] > e[i][k] + e[k][j]) //如果当前i-->j的距离大于i-->k--->j的距离之和 e[i][j] = e[i][k] + e[k][j];//更新从i--->j的最短路径 } // 时间复杂度:O(N^3) // 不能使用的情况:边中含有负权值 //二、单源最短路径算法——dijkstra //1、思想描述:当Q(一开始为所有节点的集合)非空时, //不断地将Q中的最小值u取出,然后放到S(最短路径的节点的集合)集合中, //然后遍历所有与u邻接的边,如果可以进行松弛, //则对便进行相应的松弛。。。 //2、实现 /** * 返回从v---->到target的最短路径 */ int dijkstra(int v) { int i; for(i = 1 ; i <= n ; ++i) { //初始化 s[i] = 0;//一开始,所有的点均为被访问过 dis[i] = map[v][i]; } dis[v] = 0; s[v] = true; for(i = 1 ; i < n ; ++i) { int min = inf,pos,j; for(j = 1 ; j <= n ; ++j)//寻找目前的最短路径的最小点 if(!s[j] && dis[j] < min) { min = dis[j]; pos = j; } s[pos] = 1; for(j = 1 ; j <= n ; j++)//遍历u的所有的邻接的边 if(!s[j] && dis[j] > dis[pos] + map[pos][j]) dis[j] = dis[pos] + map[pos][j];//对边进行松弛 } return dis[target]; } //3.基本结构 int s[maxn];//用来记录某一点是否被访问过 int map[maxn][maxn];//地图 int dis[maxn];//从原点到某一个点的最短距离(一开始是估算距离) //4.条件:使用dijkstra解决的题目一般有以下的特征: //给出点的数目、边的数目、起点和终点、边的信息(,并且边不包含负边权的值).求从起点到终点的最短路径的距离 //起点:用于dijkstra(int v)中的v //终点:用于return dis[target]中的target //边的信息:用于初始化map[][] //三:使用 bellmen-ford 算法 //算法介绍: //思想:其实bellman-ford的思想和dijkstra的是很像的, //其关键点都在于不断地对边进行松弛。 //而最大的区别就在于前者能作用于负边权的情况。 //其实现思路还是在求出最短路径后, //判断此刻是否还能对便进行松弛, //如果还能进行松弛,便说明还有负边权的边 //实现: bool bellmen_ford() { for(int i=1; i<=n; i++) dis[i]=inf; dis[source]=0; for(int i=1; i) { for(int j=1; j<=m; j++) { dis[edge[j].v] = min(dis[edge[j].v],dis[edge[j].u] + edge[j].weight); dis[edge[j].u] =min(dis[edge[j].u],dis[edge[j].v] + edge[j].weight) ; } } for(j = 1 ; j <= m ; ++j) //判断是否有负边权的边 if(dis[edge[j].v] > dis[edge[j].u] + edge[j].weight) return false; return true; } //基本结构: struct Edge{ int u,v,weight; }edge[maxn]; int dis[maxn]; //条件:其实求最短路径的题目的基本条件都是点数,边数,起点终点 //四、使用spfa算法来解决 //思想:用于求单源最短路经,可以适用于负边权的情况(不过他已经死了
大佬给的网站:Graph Editor