zoukankan      html  css  js  c++  java
  • 模板

    推荐一份大佬写的模板

    /*
    	2018.12.2
    	今天自习课闲来无事,把部分学过的模板了打一遍,集中于此文件,便于未来复习
    	2018.12.3
    	继续补坑
    	2018.12.4
    	翘了一节微机课来补坑
    	2018.12.5
    	update lct
    	2018.12.6
    	update quickRead
    	2018.12.9
    	update sort
    	2018.12.12
    	update 时隔多天, update inv && suffixSort
    	2018.12.23
    	update string && Möbius
    	2019.01.21
    	准备期末考试,时隔一个月才来机房,然而期末依然炸了qwq
    	update 杜教筛
    	2019.02.14
    	update CG
    	2019.04.03
    	update splay FFT graph
            2021.07.08
            修改了部分单词拼写错误,觉得自己两年前就像个sb
    */
    
    /*
    	所有代码未经编译,正确性未知,如有错误欢迎指正
    	code by Ηydra
    */
    #include <algorithm>
    #include <cctype>
    #include <complex>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <string>
    #include <vector>
    #define min(l, r) ((l) < (r) ? (l) : (r))
    #define max(l, r) ((l) < (r) ? (r) : (l))
    using std::swap;
    namespace init
    {
    // Not Recommended
    // #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
    // char buf[1 << 21], *p1 = buf, *p2 = buf;
    // 需C++11
    template <typename T>
    void rd(T &s)
    {
    	bool p = 0;
    	char ch;
    	s = 0;
    	while (ch = getchar(), p |= ch == '-', !isdigit(ch))
    		;
    	while (s = s * 10 + ch - '0', isdigit(ch = getchar()))
    		;
    	s *= (p ? -1 : 1);
    }
    template <typename T, typename... Args>
    void rd(T &s, Args &... args)
    {
    	rd(s);
    	rd(args...);
    }
    // NOIP用
    void rd(int &s)
    {
    	s = 0;
    	int p = 0;
    	char ch;
    	while (ch = getchar(), p |= ch == '-', !isdigit(ch))
    		;
    	while (s = s * 10 + ch - '0', isdigit(ch = getchar()))
    		;
    	s *= (p ? -1 : 1);
    }
    char rdch_int()
    {
    	char ch;
    	while (ch = getchar(), ch < '0' || ch > '9')
    		;
    	return ch;
    }
    char rdch_char()
    {
    	char ch;
    	while (ch = getchar(), !isalpha(ch))
    		;
    	return ch;
    }
    } // namespace init
    
    namespace segment_tree
    {
    #define mid(l, r) ((l + r) >> 1)
    #define ls(x) ((x) << 1)
    #define rs(x) (((x) << 1) | 1)
    #define fa(x) ((x) >> 1)
    #define len(x) (tree[x].r - tree[x].l + 1)
    const int N = 1000000;
    struct node
    {
    	long long l, r, val;
    	long long lzy1, lzy2;
    } tree[N << 4];
    inline void updata(int x)
    {
    	tree[x].val = (tree[ls(x)].val + tree[rs(x)].val);
    }
    inline void downdata(int x)
    {
    	if (tree[x].lzy2 > 1)
    	{
    		tree[ls(x)].lzy2 *= tree[x].lzy2;
    		tree[rs(x)].lzy2 *= tree[x].lzy2;
    		tree[ls(x)].lzy1 *= tree[x].lzy2;
    		tree[rs(x)].lzy1 *= tree[x].lzy2;
    		tree[ls(x)].val *= tree[x].lzy2;
    		tree[rs(x)].val *= tree[x].lzy2;
    	}
    	tree[x].lzy2 = 1;
    	if (tree[x].lzy1)
    	{
    		tree[ls(x)].lzy1 += tree[x].lzy1;
    		tree[rs(x)].lzy1 += tree[x].lzy1;
    		tree[ls(x)].val += tree[x].lzy1 * len(ls(x));
    		tree[rs(x)].val += tree[x].lzy2 * len(rs(x));
    	}
    	tree[x].lzy1 = 0;
    }
    void build(int i, int l, int r)
    {
    	tree[i].l = l;
    	tree[i].r = r;
    	tree[i].lzy1 = 0;
    	tree[i].lzy2 = 1;
    	if (l == r)
    	{
    		init::rd(tree[i].val);
    		return;
    	}
    	int m = mid(l, r);
    	build(ls(i), l, m),
    		build(rs(i), m + 1, r);
    	updata(i);
    }
    void add(int i, int l, int r, long long k)
    {
    	if (tree[i].l == l && r == tree[i].r)
    	{
    		tree[i].val += k * len(i);
    		tree[i].lzy1 += k;
    		return;
    	}
    	downdata(i);
    	int m = mid(tree[i].l, tree[i].r);
    	if (l > m)
    		add(rs(i), l, r, k);
    	else if (r <= m)
    		add(ls(i), l, r, k);
    	else
    		add(ls(i), l, m, k),
    			add(rs(i), m + 1, r, k);
    	updata(i);
    }
    void mul(int i, int l, int r, long long k)
    {
    	if (tree[i].l == l && r == tree[i].r)
    	{
    		tree[i].lzy1 *= k;
    		tree[i].val *= k;
    		tree[i].lzy2 *= k;
    		return;
    	}
    	downdata(i);
    	int m = mid(tree[i].l, tree[i].r);
    	if (l > m)
    		mul(rs(i), l, r, k);
    	else if (r <= m)
    		mul(ls(i), l, r, k);
    	else
    		mul(ls(i), l, m, k),
    			mul(rs(i), m + 1, r, k);
    	updata(i);
    }
    long long query(int i, int l, int r)
    {
    	if (tree[i].l == l && tree[i].r == r)
    		return tree[i].val;
    	downdata(i);
    	int m = mid(tree[i].l, tree[i].r);
    	if (l > m)
    		return query(rs(i), l, r);
    	else if (r <= m)
    		return query(ls(i), l, r);
    	else
    		return query(ls(i), l, m) + query(rs(i), m + 1, r);
    }
    #undef ls
    #undef rs
    #undef mid
    #undef fa
    #undef len
    
    } // namespace segment_tree
    
    namespace fenwickTree
    {
    #define lowbit(x) ((x) & -(x))
    const int N = 100000;
    int tree[N];
    int del1[N], del2[N];
    int sum[N];
    int tot;
    void add(int *d, int x, int k)
    {
    	while (x <= tot)
    		d[x] += k,
    			x += lowbit(x);
    }
    int query(int *d, int x)
    {
    	int ans = 0;
    	while (x)
    		ans += d[x],
    			x -= lowbit(x);
    	return ans;
    }
    //单点修改 区间查询
    void add_point_normal(int x, int k)
    {
    	add(tree, x, k);
    }
    int query_interval_normal(int l, int r)
    {
    	return query(tree, r) - query(tree, l - 1);
    }
    //区间修改 单点查询
    void add_interval_normal(int l, int r, int k)
    {
    	add(tree, l, k);
    	add(tree, r + 1, -k);
    }
    int query_point_normal(int x)
    {
    	return query(tree, x);
    }
    //区间修改 区间查询
    void add_interval_special(int l, int r, int k)
    {
    	add(del1, l, k);
    	add(del1, r + 1, -k);
    	add(del2, l, k * l);
    	add(del2, r + 1, -k * (r + 1));
    }
    int query_interval_special(int l, int r)
    {
    	return sum[r] + (r + 1) * query(del1, r) - query(del2, r) - (sum[l - 1] + l * query(del1, l - 1) - query(del2, l - 1));
    }
    //代替平衡树部分操作
    int hs[N]; //大部分情况需将操作数离散化
    void del(int x)
    {
    	--sum[x];
    	add(tree, x, 1);
    }
    void insert(int x)
    {
    	++sum[x];
    	add(tree, x, -1);
    }
    int find_rank(int x)
    {
    	int ans = 0, cnt = 0;
    	for (int i = 21; i >= 0; --i)
    	{
    		ans += 1 << i;
    		if (ans > tot || cnt + tree[ans] >= x)
    			ans -= 1 << i;
    		else
    			cnt += tree[ans];
    	}
    	return hs[ans + 1];
    }
    int my_rank(int x)
    {
    	int ans = 1;
    	--x;
    	while (x)
    		ans += tree[x],
    			x -= lowbit(x);
    	return ans;
    }
    int pre(int x)
    {
    	insert(x);
    	int ans = find_rank(my_rank(x) - 1);
    	del(x);
    	return ans;
    }
    int nxt(int x)
    {
    	insert(x);
    	int ans = find_rank(my_rank(x) + sum[x]);
    	del(x);
    	return ans;
    }
    #undef lowbit
    } // namespace fenwickTree
    
    namespace SPLAY
    {
    const int MAX = 200000;
    int fa[MAX], val[MAX], sze[MAX], cnt[MAX], son[MAX][2];
    int rt;
    int tot = 0;
    int fre[100000];
    int top = 0;
    int new_node()
    {
    	return top ? fre[top--] : ++tot;
    }
    void updata(int x)
    {
    	sze[x] = sze[son[x][0]] + sze[son[x][1]] + cnt[x];
    }
    void rotate(int x, int &k)
    {
    	int y = fa[x], z = fa[y];
    	bool p = son[y][1] == x;
    	if (y == k)
    		k = x;
    	else
    		son[z][son[z][1] == y] = x;
    	fa[x] = z;
    	fa[y] = x;
    	fa[son[x][p ^ 1]] = y;
    	son[y][p] = son[x][p ^ 1];
    	son[x][p ^ 1] = y;
    	updata(y);
    	updata(x);
    }
    void splay(int x, int &k)
    {
    	int y, z;
    	while (x != k)
    	{
    		y = fa[x], z = fa[y];
    		if (y != k)
    		{
    			if ((son[z][1] == y) == (son[y][1] == x))
    				rotate(y, k);
    			else
    				rotate(x, k);
    		}
    		rotate(x, k);
    	}
    }
    void insert(int &o, int x, int f)
    {
    	if (!o)
    	{
    		o = new_node();
    		val[o] = x;
    		cnt[o] = 1;
    		sze[o] = 1;
    		son[o][0] = son[o][1] = 0;
    		fa[o] = f;
    		splay(o, rt);
    	}
    	else if (x == val[o])
    	{
    		++cnt[o];
    		splay(o, rt);
    	}
    	else
    		x < val[o] ? insert(son[o][0], x, o) : insert(son[o][1], x, o);
    }
    void find(int o, int x)
    {
    	if (x == val[o])
    		splay(o, rt);
    	else
    		x < val[o] ? find(son[o][0], x) : find(son[o][1], x);
    }
    void merge(int l, int r)
    {
    	if (!l || !r)
    	{
    		rt = l ^ r;
    		return;
    	}
    	int o = l;
    	while (son[o][1])
    		o = son[o][1];
    	splay(o, l);
    	rt = l;
    	son[l][1] = r;
    	fa[r] = l;
    	updata(rt);
    }
    void del(int x)
    {
    	find(rt, x);
    	if (cnt[rt] > 1)
    	{
    		--cnt[rt];
    		--sze[rt];
    		return;
    	}
    	fre[++top] = rt;
    	fa[son[rt][0]] = fa[son[rt][1]] = 0;
    	merge(son[rt][0], son[rt][1]);
    }
    int my_rank(int x)
    {
    	insert(rt, x, 0);
    	int ans = sze[son[rt][0]];
    	del(x);
    	return ans;
    }
    int find_rank(int o, int x)
    {
    	return sze[son[o][0]] < x ? sze[son[o][0]] + cnt[o] >= x ? val[o] : find_rank(son[o][1], x - (sze[son[o][0]] + cnt[o])) : find_rank(son[o][0], x);
    }
    int pre(int x)
    {
    	int o = rt, ans = -1;
    	while (o)
    		x > val[o] ? (ans = val[o], o = son[o][1]) : o = son[o][0];
    	return ans;
    }
    int nxt(int x)
    {
    	int o = rt, ans = -1;
    	while (o)
    		x >= val[o] ? o = son[o][1] : (ans = val[o], o = son[o][0]);
    	return ans;
    }
    void dfs(int o)
    {
    	if (!o)
    		return;
    	dfs(son[o][0]);
    	std::cout << val[o] << " ";
    	dfs(son[o][1]);
    }
    } // namespace SPLAY
    
    namespace SPLAY_interval
    {
    
    const int MAXN = 5000000;
    int fa[MAXN], son[MAXN][2], sze[MAXN], val[MAXN];
    int tag1[MAXN], tag2[MAXN];
    int sum[MAXN], maxl[MAXN], maxr[MAXN], maxsum[MAXN];
    int fre[MAXN], cnt = 0, top = 0;
    int rt;
    int new_node()
    {
    	return top ? fre[top--] : ++cnt;
    }
    #define mid(l, r) (((l) + (r)) >> 1)
    #define ls(o) (son[o][0])
    #define rs(o) (son[o][1])
    void updata(int o)
    {
    	sum[o] = sum[ls(o)] + sum[rs(o)] + val[o];
    	sze[o] = sze[ls(o)] + sze[rs(o)] + 1;
    	maxl[o] = max(maxl[ls(o)], sum[ls(o)] + val[o] + maxl[rs(o)]);
    	maxr[o] = max(maxr[rs(o)], sum[rs(o)] + val[o] + maxr[ls(o)]);
    	maxsum[o] = max(max(maxsum[ls(o)], maxsum[rs(o)]), maxr[ls(o)] + val[o] + maxl[rs(o)]);
    }
    void push_down(int o)
    {
    	int v;
    	if (tag1[o])
    	{
    		int c = val[o];
    		if ((v = ls(o)))
    		{
    			tag1[v] = 1;
    			tag2[v] = 0;
    			val[v] = c;
    			sum[v] = c * sze[v];
    			maxl[v] = maxr[v] = (c > 0 ? sum[v] : 0);
    			maxsum[v] = (c > 0 ? sum[v] : c);
    		}
    		if ((v = rs(o)))
    		{
    			tag1[v] = 1;
    			tag2[v] = 0;
    			val[v] = c;
    			sum[v] = c * sze[v];
    			maxl[v] = maxr[v] = (c > 0 ? sum[v] : 0);
    			maxsum[v] = (c > 0 ? sum[v] : c);
    		}
    		tag1[o] = 0;
    	}
    	if (tag2[o])
    	{
    		if ((v = ls(o)))
    		{
    			tag2[v] ^= 1;
    			swap(ls(v), rs(v));
    			swap(maxl[v], maxr[v]);
    		}
    		if ((v = rs(o)))
    		{
    			tag2[v] ^= 1;
    			swap(ls(v), rs(v));
    			swap(maxl[v], maxr[v]);
    		}
    		tag2[o] = 0;
    	}
    }
    void rotate(int x, int &k)
    {
    	int y = fa[x], z = fa[y];
    	int p = rs(y) == x;
    	if (y == k)
    		k = x;
    	else
    		son[z][rs(z) == y] = x;
    	fa[x] = z;
    	fa[y] = x;
    	fa[son[x][p ^ 1]] = y;
    	son[y][p] = son[x][p ^ 1];
    	son[x][p ^ 1] = y;
    	updata(y);
    	updata(x);
    }
    void splay(int x, int &k)
    {
    	int y, z;
    	while (x != k)
    	{
    		y = fa[x], z = fa[y];
    		if (y != k)
    			rotate(ls(z) == y ^ ls(y) == x ? x : y, k);
    		rotate(x, k);
    	}
    }
    void init(int o)
    {
    	fa[o] = son[o][0] = son[o][1] = tag1[o] = tag2[o] = sum[o] = maxl[o] = maxr[o] = maxsum[o] = 0;
    }
    void build(int &o, int l, int r, int *a, int f)
    {
    	if (l > r)
    		return;
    	o = new_node();
    	int m = mid(l, r);
    	init(o);
    	fa[o] = f;
    	val[o] = a[m];
    	sze[o] = r - l + 1;
    	if (l == r)
    	{
    		sum[o] = maxsum[o] = val[o];
    		maxl[o] = maxr[o] = max(val[o], 0);
    		return;
    	}
    	build(ls(o), l, m - 1, a, o);
    	build(rs(o), m + 1, r, a, o);
    	updata(o);
    }
    int find(int k)
    {
    	int o = rt;
    	while (true)
    	{
    		push_down(o);
    		if (sze[ls(o)] + 1 == k)
    			return o;
    		if (sze[ls(o)] + 1 > k)
    			o = ls(o);
    		else
    			k -= (sze[ls(o)] + 1), o = rs(o);
    	}
    }
    int split(int pos, int tot)
    {
    	int l = find(pos), r = find(pos + tot + 1);
    	splay(l, rt);
    	splay(r, rs(l));
    	return ls(r);
    }
    void insert(int pos, int tot, int *a)
    {
    	int l = find(pos + 1), r = find(pos + 2);
    	splay(l, rt);
    	splay(r, rs(l));
    	build(ls(r), 1, tot, a, r);
    	updata(r);
    	updata(l);
    }
    void dfs_del(int o)
    {
    	if (!o)
    		return;
    	fre[++top] = o;
    	dfs_del(ls(o));
    	dfs_del(rs(o));
    }
    void del(int pos, int tot)
    {
    	int o = split(pos, tot);
    	dfs_del(o);
    	ls(fa[o]) = 0;
    	updata(fa[o]);
    	updata(rt);
    }
    void modify(int pos, int tot, int c)
    {
    	int o = split(pos, tot);
    	val[o] = c;
    	sum[o] = c * sze[o];
    	if (c > 0)
    		maxsum[o] = maxl[o] = maxr[o] = sum[o];
    	else
    		maxsum[o] = c, maxl[o] = maxr[o] = 0;
    	tag1[o] = 1;
    	tag2[o] = 0;
    	updata(fa[o]);
    	updata(rt);
    }
    void reverse(int pos, int tot)
    {
    	int o = split(pos, tot);
    	tag2[o] ^= 1;
    	swap(maxl[o], maxr[o]);
    	swap(ls(o), rs(o));
    	updata(fa[o]);
    	updata(rt);
    }
    int get_sum(int pos, int tot)
    {
    	int o = split(pos, tot);
    	return sum[o];
    }
    int max_sum()
    {
    	return maxsum[rt];
    }
    void main(int *a, int n)
    {
    	a[1] = a[n + 2] = maxsum[0] = -0x3f3fffff;
    	build(rt, 1, n + 2, a, 0);
    }
    #undef ls
    #undef rs
    #undef mid
    } // namespace SPLAY_interval
    
    namespace lct
    {
    const int N = 1000000;
    int cnt;
    int head[N], nxt[N], to[N];
    int sze[N], son[N], dep[N], top[N], rk[N], id[N], fa[N], ed[N];
    void dfs1(int u)
    {
    	sze[u] = 1;
    	for (int i = head[u]; i; i = nxt[i])
    	{
    		int v = to[i];
    		if (v == fa[i])
    			continue;
    		dep[v] = dep[u] + 1;
    		fa[v] = u;
    		dfs1(v);
    		sze[u] += sze[v];
    		if (sze[v] > sze[son[u]])
    			son[u] = v;
    	}
    }
    void dfs2(int u, int t)
    {
    	top[u] = t;
    	id[u] = ++cnt;
    	rk[cnt] = u;
    	if (son[u])
    		dfs2(son[u], t);
    	for (int i = head[u]; i; i = nxt[i])
    	{
    		int v = to[i];
    		if (v == fa[u] || v == son[u])
    			continue;
    		dfs2(v, v);
    	}
    	ed[u] = cnt;
    }
    void add1(int x, int y, int k)
    {
    	while (top[x] != top[y])
    	{
    		if (dep[top[x]] < dep[top[y]])
    			std::swap(x, y);
    		fenwickTree::add_interval_special(id[top[x]], id[x], k);
    		x = fa[top[x]];
    	}
    	if (dep[x] < dep[y])
    		std::swap(x, y);
    	fenwickTree::add_interval_special(id[y], id[x], k);
    }
    int query1(int x, int y)
    {
    	int ans = 0;
    	while (top[x] != top[y])
    	{
    		if (dep[top[x]] < dep[top[y]])
    			std::swap(x, y);
    		ans += fenwickTree::query_interval_special(id[top[x]], id[x]);
    		x = fa[top[x]];
    	}
    	if (dep[x] < dep[y])
    		std::swap(x, y);
    	ans += fenwickTree::query_interval_special(id[y], id[x]);
    	return ans;
    }
    void add2(int x, int k)
    {
    	fenwickTree::add_interval_special(id[x], ed[x], k);
    }
    int query2(int x)
    {
    	return fenwickTree::query_interval_special(id[x], ed[x]);
    }
    } // namespace lct
    
    namespace eulerFunction
    {
    const int N = 10000000;
    int vis[N];
    int phi[N];
    int pri[N], cnt;
    long long SolveWithlogN(long long n)
    {
    	int sum = n;
    	for (long long i = 1; i * i <= n; ++i)
    		if (n % i == 0)
    		{
    			sum -= sum / i;
    			while (n % i == 0)
    				n /= i;
    		}
    	if (n > 1)
    		sum -= sum / n;
    	return sum;
    }
    int main(int n)
    {
    	vis[1] = 1;
    	for (int i = 2; i <= n; ++i)
    	{
    		if (!vis[i])
    			pri[++cnt] = i,
    			phi[i] = i - 1;
    		for (int j = i * 2; pri[j] * i <= n; ++j)
    		{
    			vis[pri[j] * i] = 1;
    			if (i % pri[j] == 0)
    			{
    				phi[i * pri[j]] = phi[i] * pri[j];
    				break;
    			}
    			else
    				phi[i * pri[j]] = phi[i] * phi[pri[j]];
    		}
    	}
    	return 0;
    }
    } // namespace eulerFunction
    
    namespace prime
    {
    void solveWithN(int n)
    {
    	eulerFunction::main(n);
    }
    bool solveWithsqrtN(long long n)
    {
    	if (n == 1)
    		return 0;
    	for (long long i = 2; i * i <= n; ++i)
    		if (n % i == 0)
    			return 0;
    	return 1;
    }
    bool solve_develop(int n)
    {
    	if (n == 1)
    		return 0;
    	if (n == 2 || n == 3)
    		return 1;
    	if (n % 6 != 1 && n % 6 != 5)
    		return 0;
    	for (long long i = 5; i * i <= n; i += 6)
    		if (n % i == 0 || n % (i + 2) == 0)
    			return 0;
    	return 1;
    }
    } // namespace prime
    
    namespace qpow
    {
    //please use this when p approaches LONG_LONG_MAX
    //warning : this function is very slow(logB)
    long long mul(long long a, long long b, long long p)
    {
    	long long s = 0;
    	for (; b; b >>= 1, a = (a + a) % p)
    		if (b & 1)
    			s = (s + a) % p;
    	return s;
    }
    long long pow_special(long long a, long long b, long long p)
    {
    	long long s = 1;
    	for (; b; b >>= 1, a = mul(a, a, p))
    		if (b & 1)
    			s = mul(s, a, p);
    	return s;
    }
    long long pow_normal(long long a, long long b, long long p)
    {
    	long long s = 1;
    	for (; b; b >>= 1, a = (a * a % p))
    		if (b & 1)
    			s = (s * a) % p;
    	return s;
    }
    } // namespace qpow
    
    //haven't finished
    namespace exgcd
    {
    typedef long long ll;
    void exgcd(ll a, ll b, ll &x, ll &y, ll &gcd)
    {
    	if (!b)
    		x = 1,
    		y = 0,
    		gcd = a;
    	else
    		exgcd(b, a % b, y, x, gcd),
    			y -= (a / b) * x;
    }
    // ax = 1 (mod p)
    // (a, p) = 1
    ll inv(ll a, ll p)
    {
    	ll x, y, g;
    	exgcd(a, p, x, y, g);
    	if (g != 1)
    		return -1;
    	while (x < 0)
    		x += p;
    	return x;
    }
    } // namespace exgcd
    
    namespace inv
    {
    typedef long long ll;
    // p is a prime && (a, p) == 1
    ll FermatLittleTheorem(ll a, ll p)
    {
    	return qpow::pow_special(a, p - 2, p);
    	// return qpow::pow_normal(a, p - 2, p);
    }
    // (a, p) == 1
    ll EulerTheorem(ll a, ll p)
    {
    	return qpow::pow_special(a, eulerFunction::SolveWithlogN(p) - 1, p);
    	// return qpow::pow_normal(a, eulerFunction::SolveWithlogN(p) - 1, p);
    }
    ll exgcd(ll a, ll p)
    {
    	return exgcd::inv(a, p);
    }
    void solve_normal(ll n, ll p, ll *ans)
    {
    	ans[1] = 1;
    	for (ll i = 2; i <= n; ++i)
    	{
    		ans[i] = (-(p / i) * ans[p % i]) % p;
    		if (ans[i] < 0)
    			ans[i] += p;
    	}
    }
    void solve_fac(ll p, ll *fac, ll *facinv, ll *inv)
    {
    	facinv[0] = fac[0] = 1;
    	for (ll i = 1; i < p; ++i)
    		fac[i] = fac[i - 1] * i % p;
    	facinv[p - 1] = EulerTheorem(fac[p - 1], p);
    	for (ll i = p - 2; i >= 1; --i)
    		facinv[i] = facinv[i + 1] * i % p;
    	for (ll i = 1; i < p; ++i)
    		inv[i] = facinv[i] * fac[i - 1] % p;
    }
    // O(n + logp) 离线求n个数在模p意义下的乘法逆元
    void solve_special(int n, ll *a, ll *s, ll *invs, ll *inv, ll MOD)
    {
    	s[0] = 1;
    	for (int i = 1; i <= n; ++i)
    		s[i] = (s[i - 1] * a[i]) % MOD;
    	invs[n] = qpow::pow_special(s[n], MOD - 2, MOD);
    	for (int i = n - 1; i >= 1; --i)
    		invs[i] = invs[i + 1] * a[i + 1] % MOD;
    	for (int i = 1; i <= n; ++i)
    		inv[i] = invs[i] * s[i - 1] % MOD;
    }
    } // namespace inv
    
    namespace Möbius
    {
    const int N = 10000000;
    int mu[N] = {0}, vis[N] = {0}, pri[N] = {0}, cnt = 0;
    void get_mu(int n)
    {
    	mu[1] = vis[1] = 1;
    	for (int i = 2; i <= n; ++i)
    	{
    		if (!vis[i])
    			pri[++cnt] = i,
    			mu[i] = -1;
    		for (int j = 1; j <= cnt && pri[j] * i <= n; ++j)
    		{
    			vis[i * pri[j]] = 1;
    			if (i % pri[j] == 0)
    				break;
    			mu[i * pri[j]] = -mu[i];
    		}
    	}
    }
    //f(n) = n / 1 + n / 2 + ... + n / n
    int get_sum(int n)
    {
    	int ans = 0;
    	for (int l = 1, r; l <= n; l = r + 1)
    	{
    		r = (n / (n / l));
    		ans += (r - l + 1) * (n / l);
    	}
    	return ans;
    }
    } // namespace Möbius
    
    namespace sum
    {
    typedef long long LL;
    const int maxn = 1700000;
    int N;
    LL s1[maxn + 100], s2[1300];
    int vis[1300];
    LL S(int n)
    {
    	if (n <= maxn)
    		return s1[n];
    	int x = N / n;
    	if (vis[x])
    		return s2[x];
    	vis[x] = 1;
    	LL &ans = s2[x];
    	ans = (1 + n) * 1ll * n / 2;
    	for (int l = 2, r; l <= n; l = r + 1)
    	{
    		r = (n / (n / l));
    		ans -= (r - l + 1) * S(n / l);
    	}
    	return ans;
    }
    } // namespace sum
    
    namespace FFT
    {
    const int MAXN = 500000;
    struct comp
    {
    	double x, y;
    	comp(double _x = 0, double _y = 0) : x(_x), y(_y) {}
    } A[MAXN], B[MAXN], eps[MAXN], ieps[MAXN];
    comp operator+(comp a, comp b)
    {
    	return comp(a.x + b.x, a.y + b.y);
    }
    comp operator-(comp a, comp b)
    {
    	return comp(a.x - b.x, a.y - b.y);
    }
    comp operator*(comp a, comp b)
    {
    	return comp(a.x * b.x - a.y * b.y, a.x * b.y + a.y * b.x);
    }
    const double pi = acos(-1);
    void init(int len)
    {
    	for (int i = 0, l; l = (1 << i), l <= len; ++i)
    	{
    		eps[i] = comp(cos(2 * pi / l), sin(2 * pi / l));
    		ieps[i] = comp(cos(2 * pi / l), -sin(2 * pi / l));
    	}
    }
    void FFT(comp *x, int len, comp *p)
    {
    	for (int i = 0, j = 0; i < len; ++i)
    	{
    		if (i > j)
    			std::swap(x[i], x[j]);
    		for (int l = len >> 1; (j ^= l) < l; l >>= 1)
    			;
    	}
    	for (int i = 1, l; (l = 1 << i) <= len; ++i)
    	{
    		int mid = l >> 1;
    		for (int j = 0; j < len; j += l)
    		{
    			comp w0(1);
    			for (int k = j; k < j + mid; ++k)
    			{
    				comp t = w0 * x[k + mid];
    				x[k + mid] = x[k] - t;
    				x[k] = x[k] + t;
    				w0 = w0 * p[i];
    			}
    		}
    	}
    }
    int main()
    {
    	int n, m;
    	init::rd(n, m);
    	for (int i = 0; i <= n; ++i)
    		init::rd(A[i].x);
    	for (int i = 0; i <= m; ++i)
    		init::rd(B[i].x);
    	int len = 1;
    	while (len <= n + m)
    		len <<= 1;
    	init(len);
    	FFT(A, len, eps);
    	FFT(B, len, eps);
    	for (int i = 0; i <= len; ++i)
    		A[i] = A[i] * B[i];
    	FFT(A, len, ieps);
    	for (int i = 0; i <= n + m; ++i)
    		printf("%d ", int(A[i].x / len + 0.5));
    	return 0;
    }
    } // namespace FFT
    
    namespace linearBasis
    {
    // 线性基是竞赛中常用来解决子集异或一类题目的算法
    typedef long long LL;
    const int MAXL = 60;
    int n;
    LL a[MAXL + 5];
    std::vector<LL> v;
    void insert(LL t)
    {
    	for (int j = MAXL; j >= 0; --j)
    	{
    		if (!(t & (1ll << j)))
    			continue;
    		if (a[j])
    			t ^= a[j];
    		else
    		{
    			for (int k = 0; k < j; ++k)
    				if (t & (1ll << k))
    					t ^= a[k];
    			for (int k = j + 1; k <= MAXL; ++k)
    				if (a[k] & (1ll << j))
    					a[k] ^= t;
    			a[j] = t;
    			return;
    		}
    	}
    }
    void move_into_vector()
    {
    	v.clear();
    	for (int i = 0; i <= MAXL; ++i)
    		if (a[i])
    			v.push_back(a[i]);
    }
    void merge(LL *b)
    {
    	for (int i = 0; i <= MAXL; ++i)
    		insert(b[i]);
    }
    LL query_MAX()
    {
    	LL ans = 0;
    	for (int i = 0; i <= MAXL; ++i)
    		ans ^= a[i];
    	return ans;
    }
    // 询问第k小
    LL query_kth(LL k)
    {
    	LL ans = 0;
    	if ((int)v.size() != n)
    		--k;
    	if (k >= 1ll << v.size())
    		return -1;
    	for (size_t i = 0; i < v.size(); ++i)
    		if (k & (1ll << i))
    			ans ^= v[i];
    	return ans;
    }
    } // namespace linearBasis
    
    namespace SORT
    {
    #define mid(l, r) (((l) + (r)) >> 1)
    void bubbleSort(int *a, int n)
    {
    	for (int i = 1; i < n; ++i)
    		for (int j = n - 1; j >= i; --j)
    			if (a[j] > a[j + 1])
    				std::swap(a[j], a[j + 1]);
    }
    void selectionSort(int *a, int n)
    {
    	for (int i = 1; i < n; ++i)
    		for (int j = i + 1; j <= n; ++j)
    			if (a[i] > a[j])
    				std::swap(a[i], a[j]);
    }
    void insertSort(int *a, int n)
    {
    	std::vector<int> v;
    	v.push_back(a[1]);
    	for (int i = 2; i <= n; ++i)
    		v.insert(std::lower_bound(v.begin(), v.end(), a[i]), a[i]);
    	for (int i = 1; i <= n; ++i)
    		a[i] = v[i - 1];
    }
    void mergeSort(int *a, int n, int l, int r)
    {
    	if (l == r)
    		return;
    	int m = mid(l, r);
    	mergeSort(a, n, l, m);
    	mergeSort(a, n, m + 1, r);
    	std::inplace_merge(a + l, a + m + 1, a + r + 1);
    	// const int N = 100000;
    	// int b[N];
    	// int l1 = l, r1 = m + 1, l2 = m + 1, r2 = r + 1, p = l;
    	// while (l1 < r1 && l2 < r2)
    	// 	if (a[l1] <= a[l2])
    	// 		b[p++] = a[l1++];
    	// 	else
    	// 		b[p++] = a[l2++];
    	// while (l1 < r1)
    	// 	b[p++] = a[l1++];
    	// while (l2 < r2)
    	// 	b[p++] = a[l2++];
    	// for (int i = l; i <= r; ++i)
    	// 	a[i] = b[i];
    }
    void quickSort(int *a, int n, int l, int r)
    {
    	int x = l, y = r, m = a[mid(l, r)];
    	do
    	{
    		while (a[l] < m)
    			++l;
    		while (a[r] > m)
    			--r;
    		if (l <= r)
    			std::swap(a[l++], a[r--]);
    	} while (l <= r);
    	if (l < y)
    		quickSort(a, n, l, y);
    	if (r > x)
    		quickSort(a, n, x, r);
    }
    #undef mid
    } // namespace SORT
    
    namespace suffixSort
    {
    const int MAXN = 2000000;
    int tax[MAXN], tp[MAXN], rak[MAXN], sa[MAXN];
    // N : 后缀个数 M : 字符集大小
    void redixSort(int N, int M)
    {
    	for (int i = 0; i <= M; ++i)
    		tax[i] = 0;
    	for (int i = 1; i <= N; ++i)
    		++tax[rak[i]];
    	for (int i = 1; i <= M; ++i)
    		tax[i] += tax[i - 1];
    	for (int i = N; i >= 1; --i)
    		sa[tax[rak[tp[i]]]--] = tp[i];
    }
    void suffixSort(char *ch, int len)
    {
    	int M = 'z' - '0' + 1;
    	for (int i = 1; i <= len; ++i)
    		rak[i] = ch[i] - '0' + 1,
    		tp[i] = i;
    	redixSort(len, M);
    	int p = 0;
    	for (int w = 1; p < len; w <<= 1, M = p)
    	{
    		//这里的p仅为计数器
    		p = 0;
    		for (int i = 1; i <= w; ++i)
    			tp[++p] = len - w + i;
    		for (int i = 1; i <= len; ++i)
    			if (sa[i] > w)
    				tp[++p] = sa[i] - w;
    		redixSort(len, M);
    		std::swap(rak, tp); //此时tp为临时数组用于更新下次字符集和rak数组, 上一次的tp以被丢弃
    		rak[sa[1]] = 1;
    		//这里的p用于统计字符集大小
    		p = 1;
    		for (int i = 2; i <= len; ++i)
    			rak[sa[i]] = (tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w]) ? p : ++p;
    	}
    }
    char ch[MAXN];
    void run()
    {
    	std::cin >> (ch + 1);
    	int len = strlen(ch + 1);
    	suffixSort(ch, len);
    }
    } // namespace suffixSort
    
    namespace KMP
    {
    //数组从一开始储存哦 qwq
    void kmp(char *s1, char *s2, int l1, int l2, int *nxt, int *ans, int &cnt)
    {
    	cnt = 0;
    	nxt[1] = 0;
    	for (int i = 2; i <= l2; ++i)
    	{
    		int p = nxt[i - 1];
    		while (s2[p + 1] != s2[i] && p)
    			p = nxt[p];
    		nxt[i] = s2[p + 1] == s2[i] ? p + 1 : 0;
    	}
    	int j = 0;
    	for (int i = 1; i <= l1; ++i)
    	{
    		while (j && s1[i] != s2[j + 1])
    			j = nxt[j];
    		if (s1[i] == s2[j + 1])
    			++j;
    		if (j == l2)
    			ans[++cnt] = j,
    			j = nxt[j];
    	}
    }
    } // namespace KMP
    
    namespace manacher
    {
    const int N = 41000000;
    void init(char *ch1, char *ch2, int len1, int &len2)
    {
    	len2 = 1;
    	ch2[0] = '$';
    	ch2[1] = '#';
    	for (int i = 0; i < len1; ++i)
    	{
    		ch2[++len2] = ch1[i];
    		ch2[++len2] = '#';
    	}
    }
    int manachar(char *ch, int len)
    {
    	int l[N] = {0}, id = 0, md = 0, ans = 0;
    	for (int i = 1; i <= len; ++i)
    	{
    		if (md > i)
    			l[i] = min(md - i, l[id * 2 - i]);
    		else
    			l[i] = 1;
    		while (ch[i - l[i]] == ch[i + l[i]])
    			++l[i];
    		if (i + l[i] > md)
    			md = i + l[i],
    			id = i;
    	}
    	for (int i = 1; i <= len; ++i)
    		ans = max(ans, l[i]);
    	return ans - 1;
    }
    } // namespace manacher
    
    namespace trie
    {
    const int N = 100000;
    struct node
    {
    	int son[100];
    	int val;
    	int x;
    	int fail;
    	node()
    	{
    		for (int i = 0; i < 100; ++i)
    			son[i] = 0;
    		val = x = fail = 0;
    	}
    } trie[N];
    int head[N], nxt[N], val[N];
    int x[N];
    int root;
    int cnt;
    void add_normal(char *ch, int len)
    {
    	int o = root;
    	for (int i = 0; i < len; ++i)
    	{
    		if (trie[o].son[ch[i] - '0'])
    		{
    			o = trie[o].son[ch[i] - '0'];
    		}
    		else
    		{
    			trie[o].son[ch[i] - '0'] = ++cnt;
    			o = cnt;
    		}
    	}
    	++trie[o].x;
    }
    void add_special(char *ch, int len)
    {
    	int o = root;
    	for (int i = 0; i < len; ++i)
    	{
    		int p = 0;
    		for (int j = head[o]; j; j = nxt[j])
    			if (val[j] == ch[i])
    				p = j;
    		if (p)
    			o = p;
    		else
    		{
    			nxt[++cnt] = head[o];
    			head[o] = cnt;
    			val[cnt] = ch[i];
    			o = cnt;
    		}
    	}
    	++x[o];
    }
    void get_fail()
    {
    	const int M = N << 4;
    	int qu[M + 2], l, r;
    	l = r = 0;
    	for (int i = '0' - '0'; i <= 'z' - '0'; ++i)
    		if (trie[root].son[i])
    			qu[r++] = trie[root].son[i];
    	while (l != r)
    	{
    		int p = qu[l++];
    		int t = trie[p].fail;
    		if (l > M)
    			l = 0;
    		for (int i = '0' - '0'; i <= 'z' - '0'; ++i)
    			if (trie[p].son[i])
    			{
    				qu[r++] = trie[p].son[i];
    				if (r > M)
    					r = 0;
    				trie[trie[p].son[i]].fail = trie[t].son[i];
    			}
    			else
    			{
    				trie[p].son[i] = trie[t].son[i];
    			}
    	}
    }
    int Aho_Corasick_Automaton(char *ch, int len)
    {
    	int ans = 0;
    	int o = root;
    	for (int i = 0; i < len; ++i)
    	{
    		o = trie[o].son[ch[i] - '0'];
    		for (int j = o; j && ~trie[j].x; j = trie[j].fail)
    			ans += trie[j].x,
    				trie[j].x = -1;
    	}
    	return ans;
    }
    } // namespace trie
    
    namespace CG
    {
    #define sqr(x) ((x) * (x))
    struct point
    {
    	double x, y;
    };
    struct segment
    {
    	point l, r;
    };
    inline double dis(point a, point b)
    {
    	return sqrt(sqr(a.x - b.x) + sqr(a.y - b.y));
    }
    struct circle
    {
    	point cen;
    	double r;
    };
    typedef std::vector<point> polygon;
    inline point make_vec(point a, point b)
    {
    	point x;
    	x.x = b.x - a.x;
    	x.y = b.y - a.y;
    	return x;
    }
    //点积 a ⊥ b时点积为0
    inline double dot(point a, point b)
    {
    	return a.x * b.x + a.y * b.y;
    }
    // 叉积 a ∥ b时叉积为0,b在a逆时针为正,否则为负
    // 几何意义是四边形不等式面积
    inline double cro(point a, point b)
    {
    	return a.x * b.y - a.y * b.x;
    }
    // 求多边形面积
    // 逆时针储存
    inline double area(polygon &a)
    {
    	double ans = cro(a[a.size()], a[0]);
    	for (std::size_t i = 0; i < a.size(); ++i)
    	{
    		ans += cro(a[i], a[i + 1]);
    	}
    	return ans / 2;
    }
    // 旋转
    inline void turn(point &a, double b)
    {
    	point t = a;
    	a.x = t.x * cos(b) - t.y * sin(b);
    	a.y = t.x * sin(b) - t.y * cos(b);
    }
    // 判断点是否在直线上
    inline bool on_line(point a, segment b)
    {
    	return cro(make_vec(a, b.l), make_vec(a, b.r)) == 0;
    }
    // 判断点是否在线段上
    inline bool on_segment(point a, segment b)
    {
    	return dis(a, b.l) + dis(a, b.r) == dis(b.l, b.r);
    }
    // 海伦公式
    inline double heron(double a, double b, double c)
    {
    	double p = (a + b + c) / 2;
    	return sqrt(p * (p - a) * (p - b) * (p - c));
    }
    #undef sqr
    } // namespace CG
    
    namespace maximumFlow
    {
    typedef long long LL;
    const int MAX = 30000;
    int n;
    int cnt = 1;
    int head[MAX], nxt[MAX], to[MAX], cap[MAX], flow[MAX];
    int dis[MAX], cur[MAX];
    int qu[(MAX << 1) + 2], ql, qr;
    void insert(int u, int v, int f)
    {
    	nxt[++cnt] = head[u];
    	to[cnt] = v;
    	cap[cnt] = f;
    	flow[cnt] = 0;
    	head[u] = cnt;
    }
    bool bfs(int s, int t)
    {
    	for (int i = 1; i <= n; ++i)
    		dis[i] = 0,
    		cur[i] = head[i];
    	ql = qr = 0;
    	qu[qr++] = s;
    	dis[s] = 1;
    	while (ql != qr)
    	{
    		int now = qu[ql++];
    		if (ql > MAX << 1)
    			ql = 0;
    		for (int i = head[now], v = to[i]; i; i = nxt[i], v = to[i])
    			if (cap[i] > flow[i] && !dis[v])
    			{
    				dis[v] = dis[now] + 1;
    				if (v == t)
    					return true;
    				qu[qr++] = v;
    				if (qr > MAX << 1)
    					qr = 0;
    			}
    	}
    	return false;
    }
    int dfs(int u, int maxflow, int t)
    {
    	if (u == t)
    		return maxflow;
    	int ans = 0, temp;
    	for (int &i = cur[u], v = to[i]; i; i = nxt[i], v = to[i])
    	{
    		if (cap[i] > flow[i] && dis[v] == dis[u] + 1)
    		{
    			temp = dfs(v, min(maxflow - ans, cap[i] - flow[i]), t);
    			flow[i] += temp;
    			flow[i ^ 1] -= temp;
    			ans += temp;
    			if (ans >= maxflow)
    				break;
    		}
    	}
    	if (!ans)
    		dis[u] = -2;
    	return ans;
    }
    LL dinic(int s, int t)
    {
    	LL ans = 0;
    	while (bfs(s, t))
    		ans += dfs(s, 0x3fffffff, t);
    	return ans;
    }
    // 无源汇有上下界可行流
    int d[MAX], k[MAX];
    int main1()
    {
    	int m, u, v, lower, upper, s, t;
    	init::rd(n, m);
    	for (int i = 1; i <= m; ++i)
    	{
    		init::rd(u, v, lower, upper);
    		d[i] = lower;
    		k[u] -= lower;
    		k[v] += lower;
    		insert(u, v, upper - lower);
    		insert(v, u, 0);
    	}
    	s = n + 1;
    	t = n + 2;
    	int sum = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (k[i] < 0)
    			insert(i, t, -k[i]),
    				insert(t, i, 0);
    		else
    			insert(s, i, k[i]),
    				insert(i, s, 0),
    				sum += k[i];
    	}
    	n += 2;
    	if (dinic(s, t) != sum)
    		printf("NO
    ");
    	else
    		printf("YES
    ");
    	return 0;
    }
    // 有源汇有上下界最大流
    int main2()
    {
    	int m, u, v, lower, upper, s, t, ss, tt;
    	init::rd(n, m, s, t);
    	for (int i = 1; i <= m; ++i)
    	{
    		init::rd(u, v, lower, upper);
    		d[i] = lower;
    		k[u] -= lower;
    		k[v] += lower;
    		insert(u, v, upper - lower);
    		insert(v, u, 0);
    	}
    	ss = n + 1;
    	tt = n + 2;
    	int sum = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (k[i] < 0)
    			insert(i, tt, -k[i]),
    				insert(tt, i, 0);
    		else
    			insert(ss, i, k[i]),
    				insert(i, ss, 0),
    				sum += k[i];
    	}
    	insert(t, s, 0x3fffffff);
    	insert(s, t, 0);
    	n += 2;
    	if (dinic(ss, tt) != sum)
    		printf("please go home to sleep
    ");
    	else
    		printf("%d
    ", dinic(s, t));
    	return 0;
    }
    // 有源汇有上下界最小流
    int main3()
    {
    	int m, u, v, lower, upper, s, t, ss, tt;
    	init::rd(n, m, s, t);
    	for (int i = 1; i <= m; ++i)
    	{
    		init::rd(u, v, lower, upper);
    		d[i] = lower;
    		k[u] -= lower;
    		k[v] += lower;
    		insert(u, v, upper - lower);
    		insert(v, u, 0);
    	}
    	ss = n + 1;
    	tt = n + 2;
    	int sum = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (k[i] < 0)
    			insert(i, tt, -k[i]),
    				insert(tt, i, 0);
    		else
    			insert(ss, i, k[i]),
    				insert(i, ss, 0),
    				sum += k[i];
    	}
    	n += 2;
    	int f = dinic(ss, tt);
    	insert(t, s, 0x3fffffff);
    	int p = cnt;
    	insert(s, t, 0);
    	f += dinic(ss, tt);
    	if (f != sum)
    		printf("please go home to sleep
    ");
    	else
    		printf("%d
    ", flow[p]);
    	return 0;
    }
    } // namespace maximumFlow
    
    int main()
    {
    }
    
  • 相关阅读:
    0101-ioc
    通过Android studio手动触发Android 上层GC(垃圾回收)的方法
    【Win10】BeyondCompare时提示"许可证密钥已被撤销"的解决办法
    Android Historian安装使用
    初探OpenCL之Mac OS上的hello world示例
    python画高斯分布图形
    深度学习优化算法总结
    《用Python玩转数据》项目—线性回归分析入门之波士顿房价预测(二)
    《用Python玩转数据》项目—线性回归分析入门之波士顿房价预测(一)
    (转)导数、偏导数、方向导数、梯度、梯度下降
  • 原文地址:https://www.cnblogs.com/happyLittleRabbit/p/10065081.html
Copyright © 2011-2022 走看看