首页 > 技术文章 > Csp-s 考前模板复习

genshy 2020-11-05 10:03 原文

来自菜鸡 genshy 的·模板。

不保证没坑

冰茶机

for(int i = 1; i <= n; i++) fa[i] = i;
int find(int x)
{
	if(fa[x] == x) return x;
	else return fa[x] = find(fa[x]);
}

Dij

void Dij()
{
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	priority_queue<pair<int,int> > q;
	q.push(make_pair(0,1)); dis[1] = 0;
	while(!q.empty())
	{
		int t = q.top().second; q.pop();
		if(vis[t]) continue;
		vis[t] = 1;
		for(int i = head[t]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(dis[to] > dis[t] + e[i].w)
			{
				dis[to] = dis[t] + e[i].w;
				q.push(make_pair(-dis[to],to));
			}
		}
	}
}

最小生成树

void msc()
{
	bool comp(node a,node b){ return a.w < b.w; }
	sort(e+1,e+m+1,comp);
	for(int i = 1; i <= m; i++)
	{
		int fx = find(e[i].u);
		int fy = find(e[i].v);
		if(fx == fy) continue;
		fa[fx] = fy;
		ans += e[i].w;
		if(--num == 1) break;
	}
}

01背包

void beibao()
{
	for(int i = 1; i <= n; i++)
	{
		for(int j = m; j >= 0; j--)
		{
			if(j >= v[i]) f[j] = max(f[j],f[j-v[i]] + w[i]); 
		}
	}
}

完全背包

void beibao_two()
{
	for(int i = 1; i <= n; i++)
	{
		for(int j = 0; j <= m; j++)
		{
			if(j >= v[i]) f[j] = max(f[j],f[j-v[i]] + w[i]);
		}
	}
}

分组背包

void beibao_three()
{
	for(int i = 1; i <= cnt; i++)
	{
		for(int j = m; j >= 0; j--)
		{
			for(int k = 1; k <= num[i]; k++)
			{
				if(j >= v[i][k]) f[j] = max(f[j],f[j-v[i][k]] + w[i][k]);
			}
		}
	}
}

快速幂

int ksm(int a,int b)
{
	int res = 1;
	for(; b; b >>= 1)
	{
		if(b & 1) res = res * a % p;
		a = a * a % p;
	}
	return res;
}

哈希

int Hsah(char *s,int len)
{
	const int base = 128;
	const int p = 998244353;
	int tmp = 1;
	for(int i = 1; i <= len; i++)
	{
		tmp = (1LL * tmp * base + s[i]) % p;
	}	
	return tmp;
}

ST 表

void ST()
{
	lg[0] = -1;
	for(int i = 1; i <= n; i++)
	{
		f[i][0] = read();
		lg[i] = lg[i>>1] +1;
	}
	for(int j = 1; j <= 20; j++)
	{
		for(int i = 1; i + (1<<j)-1 <= n; i++)
		{
			f[i][j] = max(f[i][j-1],f[i + (1<<(j-1))][j-1]);
		}
	}
	for(int i = 1; i <= m; i++)
	{
		l = read(), r = read();
		tmp = lg[r-l+1];
		printf("%d\n",max(f[l][tmp],f[r-(1<<tmp)+1][tmp]));
	}
}

负环

bool fuhuan()
{
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(num,0,sizeof(num));
	queue<int> q;
	q.push(1); dis[1] = 0; num[1] = 1; vis[1] = 1;
	while(!q.empty()) 
	{
		int t = q.front(); q.pop(); vis[t] = 0;
		for(int i = head[t]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(dis[to] > dis[t] + e[i].w)
			{
				dis[to] = dis[t] + e[i].w;
				num[to]++;
				if(num[to] > n) return 0;
				if(!vis[to]) { q.push(to); vis[to] = 1;}
			}
		}
	}
	return 1;
}

单调栈

void sta()
{
	top = 0; sta[++top] = 0;
	for(int i = 1; i <= n; i++)
	{
		while(top && a[sta[top]] >= a[i]) top--;
		l[i] = sta[top]; sta[++top] = i;
	}
}

乘法逆元

void inv()
{
	inv[1] = 1;
	for(int i = 2; i <= n; i++)
	{
		inv[i] = 1LL * (p - p/i) * inv[p % i] % p;
		printf("%lld\n",inv[i]);
	}
}

tire树

struct tire
{
	void insert(char *s)
	{
		int len = strlen(s+1), p = 1;
		for(int i = 0; i <= len; i++)
		{
			int c = s[i] - 'a';
			if(!tr[p][c]) tr[p][c] = ++tot;
			p = tr[p][c];
		}
		end[p] = 1;
	}
	bool ask(char *s)
	{
		int len = strlen(s+1), p = 1;
		for(int i = 0; i <= len; i++)
		{
			int c = s[i] - 'a';
			if(!tr[p][c]) return 0;
			p = tr[p][c];
		}
		return end[p];
	}
}

树剖Lca

struct shupou
{
	void get_tree(int x)
	{
		dep[x] = dep[fa[x]] + 1; siz[x] = 1;
		for(int i = head[x]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(to = fa[x]) continue;
			fa[to] = x;
			get_tree(to,x);
			siz[x] += siz[to];
			if(siz[to] > siz[son[x]]) son[x] = to;
		}
	}
	void dfs(int x,int topp)
	{
		top[x] = topp; dfn[x] = ++num;
		if(son[x]) dfs(son[x],topp);
		for(int i = head[x]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(to == fa[x] || to == son[x]) continue;
			dfs(to,to);
		}
	}
	int lca(int x,int y)
	{
		while(top[x] != top[y])
		{
			if(dep[top[x]] <= dep[top[y]]) swap(x,y);
			x = fa[top[x]];
		}
		return dep[x] <= dep[y] ? x : y;
	}
}

线段树

struct Segment_Tree
{
	void up(int o){ sum(o) = sum(o<<1) + sum(o<<1|1); }
	void cover(int o,int val)
	{
		sum(o) += (r(o) - l(o) + 1) * val;
		tag(o) += val;
	}
	void down(int o)
	{
		if(tag(o))
		{
			cover(o<<1,tag(o));
			cover(o<<1|1,tag(o));
			tag(o) = 0;
		}
	}
	void build(int o,int L,int R)
	{
		l(o) = L, r(o) = r;
		if(L == R)
		{
			sum(o) = w[L];
			return;
		}
		int mid = (L + R)>>1;
		build(o<<1,L,mid);
		build(o<<1|1,mid+1,R);
		up(o);
	}
	void chenge(int o,int L,int R,int val)
	{
		if(L <= l(o) && R >= r(o))
		{
			cover(o,val);
			return;
		}
		down(o);
		int mid = (l(o) + r(o))>>1;
		if(L <= mid) chenge(o<<1,L,R,val);
		if(R > mid) chenge(o<<1|1,L,R,val);
		up(o);
	}
	int query(int o,int L,int R)
	{
		int res = 0;
		if(L <= l(o) && R >= r(o)) return sum(o);
		down(o);
		int mid = (l(o) + r(o))>>1;
		if(L <= mid) res += query(o<<1,L,R);
		if(R > mid) res += query(o<<1|1,L,R);
		return res;
	}
	void merage(int &x,int y)
	{
		if(!x) {x = y; return;}
		if(!y) return;
		tr[x].sum += tr[y].sum;
		tr[x].lc = mergae(tr[x].lc,tr[y].lc);
		tr[x].rc = mergae(tr[x].rc,tr[y].rc);
	}
}

树状数组

struct BIT 
{
    int lowbit(int x) {return x & -x;}
    void chenge(int x,int val)
    {
        for(; x <= n; x += lowbit(x)) tr[x] += val;
    }
    int query(int x)
    {
        int res = 0;
        for(; x; x -= lowbit(x)) res += tr[x];
        return res;
    }
}

单调队列

struct queue
{
	int l = 1, r = 0;
	for(int i = 1; i <= n; i++)
	{
		while(l <= r && q[l] < i-k) l++;
		while(l <= r && a[q[r]] >= a[i]) r--;
		q[++r] = i;
		if(i > k) printf("%d\n",q[l]);
	}
}

矩阵快速幂,矩阵乘法

struct Matrix
{
	struct node
	{
		int a[2][2];
	};
	node operator * (node x,node y)
	{
		node c;
		for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) c.a[i][j] = 0;
		for(int i = 0; i < 2; i++)
		{
			for(int j = 0; j < 2; j++)
			{
				for(int k = 0; k < 2; k++)
				{
					c.a[i][j] = (c.a[i][j] + x.a[i][k] * y.a[k][j]) % p;
				}
			}
		}
	}
	node ksm(node a,int b)
	{
		node res;
		for(int i = 0; i < 2; i++)
		{
			for(int j = 0; j < 2; j++)
			{
				if(i == j) res.a[i][j] = 1;
				else res.a[i][j] = 0;
			}
		}
		for(; b; b >>= 1)
		{
			if(b & 1) res = res * a % p;
			a = a * a % p;
		}
		return res;
	}
}

kmp

struct kmp
{
	void init()
	{
		int j = 0;
		for(int i = 2; i <= m; i++)
		{
			while(j && a[i] != a[j+1]) j = net[j];
			if(a[i] == a[j+1]) j++;
			net[i] = j;
		}
		j = 0;
		for(int i = 1; i <= n; i++)
		{
			while(j && b[i] != a[j+1]) j = net[j];
			if(b[i] == a[j+1]) j++;
			if(j == m) ans++;
		}
	}
}

spfa

void spfa()
{
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	queue<int> q;
	q.push(1); dis[1] = 0; vis[1] = 1;
	while(!q.empty())
	{
		int t= q.front(); q.pop(); vis[t] = 0;
		for(int i = head[t]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(dis[to] > dis[t] + e[i].w)
			{
				dis[to] = dis[t] + e[i].w;
				if(!vis[to]) { q.push(to); vis[to] = 1; }
			}
		}
	}
}

二分图染色,匈牙利算法

struct erfentu
{
	bool xiongyali(int x)
	{
		for(int i = head[x]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(!vis[to])
			{
				vis[to] = 1;
				if(!match[to] || dfs(match[to]))
				{
					match[to] = x;
					return 1; 
				}
			}
		}
		return 0;
	}
	void dfs(int x,int col)
	{
		if(flag) return;
		col[x] = col;
		for(int i = head[x]; i; i = e[i].net)
		{
			if(!col[e[i].to]) dfs(e[i].to,3-col);
			if(col[x] == col[e[i].to]){
			    flag = 1;
			    return;
			}
		}
	}
}

exgcd

void exgcd(int a,int b,int &x,int &y)
{
	if(b == 0)
	{
		x = 1;
		y = 0;
		return;
	}
	exgcd(b,a % b,y,x);
	y -= a/b * x;
}

割点,强连通分量

struct tarjain()
{
	void tarjain(int x)//割点 
	{
		dfn[x] = low[x] = ++num; 
		for(int i = head[x]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(!dfn[to])
			{
				tarjain(to);
				low[x] = min(low[x],low[to]);
				if(low[to] >= dfn[x])
				{
					flag++;
					if(x != rt || flag > 1) cut[x] = true;
				}
			}
			else low[x] = min(low[x],dfn[to]);
		}
	}
	void tarjain(int x)//强连通
	{
		dfn[x] = low[x] = num++;
		sta[++top] = x; vis[x] = 1;
		for(int i = head[x]; i; i = e[i].net)
		{
			int to = e[i].to;
			if(!dfn[to])
			{
				tarjain(to);
				low[x] = min(low[x],low[to]);
			}
			else if(vis[to]) 
			{
				low[x] = min(low[x],dfn[to]);
			}
		}
		if(dfn[x] == low[x]){
			cnt++; int y;
			do{
				y = sta[top--];
				vis[y] = 0;
				sum[cnt] += a[y];
				c[y] = cnt;
			}while(x != y);
		}	
	} 
}

manacher算法

void manacher
{
	len = len * 2 + 2; 
	c[0] = '@' , c[1] = '#';
    int maxR = -1;//现在最右边的端点 
    int center = -1;//当前的回文中心 
	for(int i = 1; i <= len; i++)
	{
		if(i < maxR) r[i] = min(maxR-i, r[center*2-i]);
		else r[i] = 1;
		while(c[i+r[i]] == c[i-r[i]]) r[i]++;
		if(i + r[i] - 1 > maxR)
		{
			maxR = i + r[i] - 1;
			center = i;
		}
		ans = max(ans , r[i]);
	}
}

左偏树

struct left_tree
{
	int merage(int x,int y)
	{
		if(!x || !y) return x+y;
		if(tr[x].val > tr[y].val) swap(x,y);
		tr[x].rc = mergae(tr[x].rc,y);
		fa[tr[x].rc] = x;
		if(tr[tr[x].lc].dis > tr[tr[x].rc].dis) swap(tr[x].lc,tr[x].rc);
		tr[x].dis = tr[tr[x].rc].dis + 1;
		return x;
	}
	void del(int x)
	{
		tr[x].val = -1;
		fa[tr[x].lc] = tr[x].lc; fa[tr[x].rc] = tr[x].rc;
		fa[x] = merage(tr[x].lc,tr[x].rc);
	}
}

主席树

struct charman_tree
{
	int insert(int now,int l,int r,int x,int val)
	{
		int p = ++tot;
		tr[p].lc = tr[now].lc;
		tr[p].rc = tr[now].rc;
		tr[p].sum = tr[now].sum;
		if(l == r)
		{
			tr[p].sum += val;
			return p;
		}
		int mid = (l + r)>>1;
		if(x <= mid)
		{
			tr[p].lc = insert(tr[now].lc,l,mid,x,val);
		}
		if(x > mid)
		{
			tr[p].rc = insert(tr[now].rc,mid+1,r,x,val);
		}
		tr[x].sum = tr[tr[x].lc].sum + tr[tr[x].rc].sum;
		return p;
	}
	int query(int x,int y,int l,int r,int k)
	{
		if(l == r) return l;
		int mid = (l + r)>>1;
		int t = tr[tr[x].lc].sum - tr[tr[y].lc].sum;
		if(k <= t) return query(tr[x].lc,tr[y].lc,l,mid,k);
		else return query(tr[x].rc,tr[y].rc,mid+1,r,k-t);
	}
}

01tire

struct 01Tire
{
	void insert(int x)
	{
		for(int i = 1<<30; i; i>>=1)
		{
	    	bool c = x & i;
	    	if(tr[fa][c] == 0) tr[fa][c] = ++cnt;
	   	    fa = tr[fa][c];
		}
	}
	int query(int x)
	{
		int res = 0;
		for(int i = 1<<30; i; i>>=1)
		{
			bool c = x & i;
			if(tr[fa][c^1])
			{
		  		res += i;
		 	 	fa = tr[fa][c^1];
			}
			else fa = tr[fa][c]; 
		}
		return res;
	}
}

Lucas

struct Lucas
{
	int C(int n,int m)
	{
		if(n > m) return 0;
		else return jz[n] * inv[m] % p * inv[n-m] % p;
	}
	int Lucas(int n,int m)
	{
		if(m == 0) return 1;
		return C(n % p,m % p) * Lucas(n/p,m/p) % p;
	}
}

CRT

struct CRT
{
	void exgcd(int a,int b,int &x,int &y)
	{
		if(b == 0)
		{
			x = 1;
			y = 0;
			return;
		}
		exgcd(b,a % b,y,x);
		y -= a/b * x;
	}
	for(int i = 1; i <= n; i++)
	{
		M = lcm / m[i];
		x = 0; y = 0;
		exgcd(M,m[i],x,y);
		if(x < 0) x = (x % m[i] + m[i]) % m[i];
		ans = (ans + a[i] * M * x) % lcm;
	}
}

模拟退火

struct SA
{
	void SA()
	{
		double temp = 3000;
		double x = sx;
		double y = sy;
		while(temp > eps)
		{
			double xx = x + ((rand()<<1) - RAND_MAX) * temp;
			double yy = y + ((rand()<<1) - RAND_MAX) * temp;
			double nowans = calc(xx,yy);
			double bianhua = nowans - ans;
			if(bianhua < 0)
			{
				ans = nowans;
				x = xx; y = yy;
				sx = xx; sy = yy;
			} 
			else if(exp(-bianhua / temp) * RAND_MAX > rand())
			{
				x = xx; y = yy;
			}
			temp *= d;
		}
	}
	void work()
	{
		sx = tx / n;
		sy = ty / n;
		ans = calc(sx,sy);
		SA(); SA(); SA(); SA();
	}
}

dinic

struct dinic
{
	bool bfs()
	{
		memset(dep , 0 , sizeof(dep));
		queue<int> q;
		q.push(s); dep[s] = 1;
		while(!q.empty())
		{
			int x = q.front(); q.pop();
			for(int i = head[x]; i; i = e[i].net)
			{
				int to = e[i].to;
				if(e[i].w && !dep[to])
				{
					q.push(to);
					dep[to] = dep[x] + 1;
					if(to == t) return 1;
				}
			}
		}
		return 0;
	}
	int dinic(int x , int flow)
	{
		if(x == t) return flow;
		int rest = flow , k;
		for(int i = head[x]; i && rest; i = e[i].net)
		{
			int to = e[i].to; int val = e[i].w;
			if(val && (dep[to] == dep[x] + 1))
			{
				k = dinic(to , min(rest , val));
				if(!k) dep[to] = 0;
				e[i].w -= k; e[i^1].w += k;
				rest -= k;
			}
		}
		return flow - rest;
	}	
	void init()
	{
		while(bfs())
		{
			while(flow = dinic(s,inf)) ans += flow;
		}
	}
}

高斯消元

struct Gassus
{
	for(int i = 1; i <= n; i++)
	{
		int pai = i;
		while(a[pai][i] == 0 && pai <= n) pai++;
		if(pai == n+1)
		{
			puts("No Solution");
			return 0;
		}
		for(int j = 1; j <= n+1; j++) swap(a[i][j],a[pai][j]);
		double rate = a[i][i];
		for(int j = 1; j <= n+1; j++)
		{
			a[i][j] /= rate;
		}
		for(int j = 1; j <= n; j++)
		{
			if(i == j) continue;
			double rate = a[j][i] / a[i][i];
			for(int k = i; k <= n+1; k++)
			{
				a[j][k] = a[j][k] - rate * a[i][k];
			}
		}
	}
}

线性筛

void YYCH()
{
	mu[1] = 1; phi[1] = 1;
	for(int i = 2; i <= N-5; i++)
	{
		if(!check[i])
		{
			prime[++tot] = i;
			mu[i] = -1;
			phi[i] = i-1;
		}
		for(int j = 1; j <= tot && i * prime[j] <= N-5; j++)
		{
			check[i * prime[j]] = 1;
			if(i % prime[j] == 0)
			{
				mu[i * prime[j]] = 0;
				phi[i * prime[j]] = phi[i] * prime[j];
				break;
			}
			else
			{
				mu[i * prime[j]] = -mu[i];
				phi[i * prime[j]] = phi[i] * phi[prime[j]];
			}
		}
	}
}

杜教筛

int dfsmu(int n){
	if(n <= maxn) return sum[n];
	if(ans1[n]) return ans1[n];
	int ans = 1;
	for(int l = 2,r; l <= n; l = r + 1)
    {
		r = n/(n/l);
		ans -= (r-l+1) * dfsmu(n/l);
	}
	return ans1[n] = ans;
}
int dfsphi(int n){
    if(n <= maxn) return tot[n];
	if(ans2[n]) return ans2[n];
	int ans = n * (n+1) / 2;
	for(int l = 2,r; l <= n; l = r + 1)
    {
		r = n/(n/l);
		ans -= (r-l+1) * dfsphi(n/l);
	}
	return ans2[n] = ans;
}

扫描线

struct Tree
{
	struct tree
	{
		int l,r;
		int len,add;
	}tr[N<<2];
	struct node
	{
		int l,r;
		int h,tag;
		node(){}
		node(int a,int b,int c,int d){l = a, r = b,h = c,tag = d;}
	}line[N<<1];
	#define l(o) tr[o].l
	#define r(o) tr[o].r
	#define add(o) tr[o].add
	#define len(o) tr[o].len
	bool comp(node a,node b)
	{
		return a.h < b.h;
	}
	void up(int o)
	{
		if(add(o)) len(o) = d[r(o)+1] - d[l(o)];
		else len(o) = len(o<<1) + len(o<<1|1);
	}
	void build(int o,int L,int R)
	{	
		l(o) = L, r(o) = R;
		if(L == R)
		{
			len(o) = 0;
			return;
		}
		int mid = (L + R)>>1;
		build(o<<1,L,mid);
		build(o<<1|1,mid+1,R);
	}
	void chenge(int o,int L,int R,int val)
	{
		if(L <= l(o) && R >= r(o))
		{
			add(o) += val;
			up(o);
			return;
		}
		int mid = (l(o) + r(o))>>1;
		if(L <= mid) chenge(o<<1,L,R,val);
		if(R > mid) chenge(o<<1|1,L,R,val);
		up(o);
	}
	int main()
	{
		scanf("%d",&n);
		for(int i = 1; i <= n; i++)
		{
			scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
			line[2 * i - 1] = node(x1,x2,y1,1);
			line[2 * i] = node(x1,x2,y2,-1);
			b[++tot] = x1;
			b[++tot] = x2;
		}
		sort(b+1,b+tot+1);
		sort(line+1,line+2*n+1,comp);
		num = unique(b+1,b+tot+1)-b-1;
		for(int i = 1; i <= 2 * n; i++)
		{
			int id1 = lower_bound(b+1,b+num+1,line[i].l)-b;
			int id2 = lower_bound(b+1,b+num+1,line[i].r)-b;
			d[id1] = line[i].l;
			d[id2] = line[i].r;
			line[i].l = id1;
			line[i].r = id2; 
		}
		build(1,1,num);
		for(int i = 1; i < 2 * n; i++)
		{
			chenge(1,line[i].l, line[i].r-1,line[i].tag);
			ans += 1LL * tr[1].len * (line[i+1].h - line[i].h);
		}
		printf("%lld\n",ans);
	}
}

点分治

struct dianfenzhi
{
	void get_root(int x,int fa)
	{
 		max_siz[x] = 0; siz[x] = 1; 
  		for(int i = head[x]; i; i = e[i].net)
  	 	{
  		    int to = e[i].to;
   		    if(to == fa || vis[to]) continue;
   	 	    get_root(to,x);
    	    siz[x] += siz[to];
    	    max_siz[x] = max(max_siz[x],siz[to]);
		}
	   	max_siz[x] = max(max_siz[x],sum_siz-siz[x]);
	    if(max_siz[x] < max_siz[root]) root = x;
	}
	void get_dis(int x,int fa,int who)
	{
  		a[++cnt] = node(dis[x],who);
  		for(int i = head[x]; i; i = e[i].net)
		{
   		    int to = e[i].to;
    	    if(to == fa || vis[to]) continue;
    	    dis[to] = dis[x] + e[i].w;
    	    get_dis(to,x,who);
	    }
	}
	int search(int d)
	{
 		int L = 1, R = cnt, res = 0;
  		while(L <= R)
 		{
    	    int mid = (L+R)>>1;
    	    if(a[mid].d >= d)
    	    {
    	        res = mid;
    	        R = mid - 1;
    	    }
    	    else L = mid + 1;
    	}
    	return res;
	}
	void calc(int x,int d)
	{
    	dis[x] = 0; cnt = 0; 
    	for(int i = head[x]; i; i = e[i].net)
    	{
    	    int to = e[i].to;
     	   if(vis[to]) continue;
     	   dis[to] = dis[x] + e[i].w; 
     	   get_dis(to,x,to);
    	}
    	a[++cnt] = node(0,0); 
    	sort(a + 1, a + cnt + 1, comp);
    	for(int i = 1; i <= m; i++)
    	{
    	    if(ans[i]) continue;
    	    int l = 1, r = cnt;
    	    while(l <= cnt && a[l].d + a[r].d < k[i]) l++;
    	    while(l <= cnt && !ans[i])
    	    {
     	       if(k[i] - a[l].d < a[l].d) break;
    	        int id = search(k[i] - a[l].d);
    	        while(a[id].d + a[l].d == k[i] && a[id].wh == a[l].wh) id++;
    	        if(a[l].d + a[id].d == k[i]) ans[i] = 1;
    	        l++;
    	    }
    	}
	}
	void slove(int x)
	{
 	   calc(x,0); vis[x] = 1;
    	for(int i = head[x]; i; i = e[i].net)
    	{
    	    int to = e[i].to;
    	    if(vis[to]) continue;
    	    max_siz[0] = n; sum_siz = siz[to]; root = 0;
    	    get_root(to,0); slove(root);
   		}
	}
}

BSGS

struct BSGS
{
	LL ksm(LL a, LL b)
	{
		LL res = 1;
		for(; b; b >>= 1)
		{
			if(b & 1) res = res * a % p;
			a = a * a % p;
		}
		return res;
	}
	int BSGS(int a,int b,int p)
	{
		map<LL,int> hash;  hash.clear();
		int m = (int)sqrt(p);
		for(int i = 0; i <= m; i++)
		{
			LL val = ksm(a,i) * b % p;//b * a ^ i
			hash[val] = i;//放入map中 
		}
		a = ksm(a,m);//a ^ m
		for(int i = 0; i <= m; i++)
		{
			LL val = ksm(a,i);//(a^m)^i
			int j = hash.find(val) == hash.end() ? -1 : hash[val];//如果没有j就为-1 
			if(j >= 0 && i * m - j >= 0) return i * m - j;//找到一组解 
		}
		return -1;
	}		
}

推荐阅读