判断条件
无向图
因为欧拉路径中,起点与终点度数为奇数,其它点的度数均为偶数。
如果是欧拉回路,奇点的个数应该为 0。
有向图
欧拉路径中,最多只有两个点的入度不等于出度。起点出度比入度大 1,终点入度比出度大 1。
如果是欧拉回路,所有点的 入度 = 出度 。
Hierholzer算法
1 | void dfs(int u){ |
1 | int head[maxn], to[maxn * 2], nxt[maxn * 2], d[maxn * 2], tot; |
1 | namespace hld { |
模拟。
当 $(x,y)$ 满足 $ d \le x+y \le 2n-d$ 并且 $-d \le y-x\le d$ 时,$(x,y)$ 在矩形内。
直接枚举分成了几段,计算每段的值,模拟一下即可。
数论构造。
求解方程 $ x \times y = \frac{2nm}{k} $ 的整数解 $(x,y)$ 。
如果 k 模 2 为 0,令 $k = \frac k2$, $ g=\gcd(n,k)$,则 $x=\frac ng$,$y=\frac{m}{\frac kg}$。
如果 k 模 2 为 1,令 $g=\gcd(n,k)$, 则 $x=\frac ng$, $y=\frac{m}{\frac kg}$, 注意到 $x = n$ 或者 $x < \frac n2$, 则可以令 $x = 2x$ 或 $y = 2y$。
对于原问题,将输入 $a_i$ 转换成一串表示该数二进制表示多少个1,实际上我们要求区间 $[l,r]$ 满足 $2|sum(a[l \dots r])$ 且 $\max(a[l \dots r]) <= \frac 12 sum(a[l \dots r])$ 的方案数。
对于 $a_i \ge 1$,则每个数至少有一位是 1,而位数最多只有60位,那么如果序列长度大于 60,则必然满足第二个条件。
因此对于每个位置,我们预处理他的后缀和为奇数和偶数的数量,那么不考虑第二个条件,左端点为 $l$ 对答案的贡献为 $cnt[i+1][sufSum_i \% 2]$,对于长度小于 60 的后缀,暴力查询即可。
统计一下三种字符的个数。
如果每种有多于 $1$ 个字符,将其替换为没出现过的字符。
显然 $\gcd(i,i+1)=1$,直接输出即可。
统计只出现 $1$ 次的数字有哪些,如果有偶数个,对半分配即可。
出现两次的数字要么一人拿一个,要么一个人全拿,不影响答案。
出现次数大于 $2$ 的数字,如果已经可以分配了就全部给一个人即可;如果第一种是奇数个,那么分配一个出现次数大于 $2$ 的。
自闭题T^T。
考虑 $dp[i][j][state]$ 表示遍历到第 $i$ 列,有 $j$ 个联通块,第 $i$ 列状态为 $state$ 的方案数。
时间复杂度 $O(nk)=O(n^2)$。
1 | #ifdef XLor |
1 | namespace sieve{ |
1 | int dp[20][maxn]; |
1 | int dp[20][maxn]; |
后缀自动机求母串不包含给定串子串的不同子串数量
首先,需要知道求两个串最长公共子串,即维护第二个串的每个前缀与第一个串的最长公共后缀。
对母串建一个 $sam$,所有串在 $sam$ 上面跑,并维护每个 $sam$ 上每个状态与所有的最长公共后缀长度,因此每个状态对答案的贡献为 $len(s) - dep(s)$。
可以理解原来状态的对子串数量的贡献为 $len(s) - len(link(s))$,$s$ 代表的子串长度区间中每个后缀都对答案有贡献,现在我们将这个区间拆成两块更新答案。
具体来讲,在获取所有点的 $dep$ 值后,基数排序获得 $sam$ 的状态的逆序拓扑排序。
因为需要对于每个状态更新他父亲节点的 $dep$ 值,所以遍历逆序拓扑排序。
这里需要同时从自动机和后缀树两个角度同时思考,当前节点的父亲也是当前节点的后缀,但是计算 $dep$ 时是自动机视角,所以当前节点和他的父亲计算的 $dep$ 没有影响,但实际上当前节点 $dep$ 值对他的父亲是有影响的,例如当前 $dep$ 超过了父亲节点的 $len$,父亲节点对答案是没有贡献的。
1 | namespace sam { |
1 | namespace gsam { |