目录html
有一个长为 \(n\) 的序列 \(a_0,a_1,\cdots, a_{n - 1}\) ,给你三个参数 \(X,Y,Z\) 。git
定义一个好的序列知足 存在 \(0\le x < y < z < w \le n\) 使得
\[ \begin{align} \sum_{i = x}^{y - 1} a_i &= X\\ \sum_{i = y}^{z - 1} a_i &= Y\\ \sum_{i = z}^{w - 1} a_i &= Z \end{align} \]
问知足条件的序列有多少个。(对于 \(10^9 + 7\) 取模)app
\(3 \le n \le 40, 1 \le X,Z \le 5, 1 \le Y \le 7\) 且 \(1 \le a_i \le 10, a_i \in \mathbb{N^{+}}\) 。优化
一道很妙的题qwqspa
一开始以为是个思博题,而后发现怎么正向计数都会算重。指针
后来去看了下题解,原来能够转化成 \(10^n -\) 不合法的序列数,这样就不会记重了。code
但这样转化后如何记呢?数据范围十分地小,能够状压 \(dp\) 。htm
具体来讲就是把一个 \(a_i\) 拆成一个 \(1\) 和 \(a_i - 1\) 个 \(0\) 。blog
好比 \(5\) 会被拆成 \(\underline{10000}\) 。排序
而后咱们就能够把以前填的数顺次拼起来了。
这样有什么好处呢?不难发现若是一段连续的和为 \(S\) ,那么 \(S\) 转化后的集合 会是 连续一段转化后拼起来构成的集合的 子集 。
好比 \(2 + 4 = 6\) ,就有 \(\underline {100000} \in \underline{10} + \underline{1000} = \underline{101000}\) 。
那么咱们只要对于每一个位置状压前 \(X + Y + Z = 17\) 位就好了,一开始 \(X,Y,Z\) 压成的状态顺次拼到一块儿的状态,就是全部不可行的状态的本身。
枚举当前填到哪一位,以及状态,再枚举这位填什么就好了,复杂度就是 \(O(10n2^{X+Y+Z})\) 的。
要求连续和很小的时候也能够巧妙状压,注意看数据范围。
戳这个 连接 ,好写的很。
一开始会有个空串 \(S\) ,有三个操做。
而后你会进行 \(n\) 次操做,给你最后的串 \(S\) ,问有多少种不一样的操做序列知足条件。(对于 \(10^9 + 7\) 取模)
\(n \le 5000, 1 \le |S| \le n\)
一开始随便想了个 \(O(n^3)\) 的暴力,就是令 dp[i][j][k]
为当前进行了 \(i\) 次操做,串长为 \(j\) ,第一个失配的地方在 \(k\) 的操做方案数,对于当前进行什么操做分开考虑就好了。
其实正解很思博,咱们以前那个 dp
第三维是没有必要的,由于咱们发现串的形态是不会影响答案的,因此就令 dp[i][j]
为进行了 \(i\) 次操做,串长为 \(j\) 的方案数。
最后答案就是 \(\displaystyle \frac{dp[n][len]}{2^{len}}\) ,由于最后每一个串对应的方案数都是同样的,总共有 \(2^{len}\) 个串,这样就是 \(O(n ^ 2)\) 的了。
其实能够继续优化,怎么考虑计数呢,由于最后的串长要刚好为 \(len\) ,咱们能够转化成至多为 \(len\) 的答案减去至多为 \(len - 1\) 的答案。
咱们假设 \(f(x)\) 为串长至多为 \(x\) 的答案,那么表达出来就是:
\[ f(x) = \sum_{i = 0}^{n} [i - (n - i) \le x] ({n \choose i} - {n \choose i - (x + 1)}) \times 2^{i} \]
也就是咱们考虑在 \(n\) 个操做中有 \(i\) 个操做为在后面添加字符,剩余 \(n - i\) 个操做为退格操做。
\([i - (n - i) \le x]\) 意味着全部退格和添加字符操做 所有抵消 后串长不超过 \(x\) ,这是必要的条件。
\(\displaystyle {n \choose i}\) 是全部可能添加和退格操做的排列,\(-\displaystyle {n \choose i - (x + 1)}\) 是全部最后串长会超过 \(x\) 的状况。
为何会出现超过 \(x\) 的状况呢?由于会有好一些退格操做都不会产生做用,不会产生做用的若是有 \(i - (x + 1)\) 及以上个,那么就是不行的。
不难发现,把其中不会消除的 \(i - (x + 1)\) 退格操做放在排列在 \(n\) 个总操做之中的任意一个地方,对应仅对应且仅对应一组不合法的解。
最后发现每一个添加数字的操做会对应两个操做,因此还要乘上 \(2^i\) 。
预处理了阶乘和阶乘逆元后就能够作到 \(O(n)\) 的复杂度啦。
对于求最后要求形态惟一的题,能够考虑有多少个形态的方案数是和它如出一辙的,最后除去那么多就好了,一般能够下降一维的复杂度。
\(O(n^3):\) 代码戳这里。
\(O(n^2):\) 代码戳这里。
\(O(n):\) 代码戳这里。
给你两个数 \(n, s\) ,找出一个最小的数 \(b\) 使得 \(n\) 在 \(b\) 进制下的数位和为 \(s\) 。
\(n,s \le {10}^{11}\)
对于 \(< \sqrt n\) 的 \(b\) 咱们能够暴力枚举,而后逐位拆解求和,复杂度是 \(O(\sqrt n \log n)\) 的。
对于 \([\lceil \sqrt n \rceil, n]\) 的 \(b\) ,那么 \(n\) 在 \(b\) 进制下只有两位,其实就是解一个以下的方程:
\[ \begin{align} \lfloor \frac{n}{b} \rfloor + n \bmod b &= s \\ \lfloor \frac{n}{b} \rfloor + (n - \lfloor \frac{n}{b} \rfloor \times b) &= s\\ \lfloor \frac{n}{b} \rfloor (1 - b) &= s - n \\ b &= \frac{n - S}{\lfloor \frac{n}{b} \rfloor} - 1 \end{align} \]
不难发现 \(\displaystyle \lfloor \frac{n}{b} \rfloor\) 只有 \(\sqrt n\) 种取值,咱们直接整除分块,而后解方程便可。
而后对于 \(n = s\) 的点须要特判,\(b\) 此时为 \(n + 1\) 。
因此最后复杂度是 \(O(\sqrt n \log n)\) 的。
对于进制下的题,要么数位 \(dp\) ,要么考虑分状况讨论。
\(\ge \lceil \sqrt n \rceil\) 的进制只会有两位,\(< \lceil \sqrt n \rceil\) 的进制位也只有 \(\log n\) 层。
戳这里。
定义一个内部不包含循环子串 \(S\) 至少出现两次的串为好串,好比 \(\underline{a}\) 为好串,\(\underline{abab}\) 不为好串,\(\underline{cdcdc}\) 为好串。
给你一个字符串 \(w\) ,如今要把它划分红不少段好串,其中段数要尽可能少。而后问段数尽可能上的前提下,问有多少种划分方式。(对于 \(10^9 + 7\) 取模)
假设最好最优的段数为 \(l\) 。
判断一个串是否为好串能够先用 \(kmp\) ,求出每一个前缀的 \(fail\) (也就是这个前缀的最长公共先后缀 \((border)\) )
而后就能够用一个经常使用性质了:
最小循环串(不必定会出现完毕)的长度等于 \(len - border\) ,具体证实能够参考 这里 。
而后它为好串,当且仅当 \(fail_i\) 为 \(0\) 或者 \(i \mod (fail_i - i) \not = 0\) 。前者由于最小循环串是本身自己,后者由于不能彻底填满。
首先能够特殊考虑两种状况:
剩下的状况其实答案都为 \(l = 2\) ,为何呢?
由于你能够考虑把 \(1 \sim |w| - 1\) 分到一组,最后一个字母单独分红一组。
若是这样不可行的话,只有两种状况:
- 所有字母相等,前面会特判掉。
- \(1 \sim |S| - 1\) 存在一个最小循环串 \(|S|\) 至少出现两次,和最后一个拼起来后必定使得整个串不存在一个可行的最小循环串。
而后剩下计算方案数,只须要枚举断点,而后判断先后缀是否为好串便可。( \(kmp\) 预处理两次就好了)
牢记 \(border(fail)\) 与 最小循环串 互相转化的性质。
戳 这里 。
给你一颗有 \(n\) 个点的树,一开始有 \(k\) 个点有权值。问是否能让其余的点也赋上权值,使得相邻两个节点的权值差的绝对值为 \(1\) 。
若是能够,请给出一组构造方案知足条件。
\(1 \le k \le n \le 10^5\)
首先分层考虑奇偶性是否存在解。
而后你对于每一个点维护它可取的权值范围 \([l_i, r_i]\) 。
而后每次须要从儿子转移上来:
\[ l_u = \max\{l_u, l_{son} - 1\}\\ r_u = \min\{r_u, r_{son} + 1\} \]
边界就是,这个点无权值就是 \([- \infty, \infty]\) ,有权值就是 \([val_u, val_u]\) 。
若是 \(l_u > r_u\) 无解。
而后只须要从上往下随意构造一组方案便可 。
树上构造关于权值构造能够考虑奇偶性。关于差值,能够考虑每一个点的取值范围而后向上转移便可。
戳 这里 。
平面上有 \(n\) 个点,其中选出两个点 \(a, b\) ,令他们之间的曼哈顿距离为 \(D\) 。
两个点联通当且仅当这两个点之间的曼哈顿距离也为 \(D\) ,最后询问 \(a\) 所在联通块的每一个点的度数之和。
\(1 \le n \le 10^5\)
一道挺不错的套路题。
看到曼哈顿距离不难想到能够与切比雪夫距离进行转换。
切比雪夫距离:
平面上两点 \((x_1, y_1), (x_2, y_2)\) 之间的距离为 \(\max(|x_1 - x_2|, |y_1 - y_2|)\) 。
如何转换呢?考虑把原来坐标系旋转 \(45^{\circ}\) 。原来的坐标 \((x, y)\) 就变成了 \((x + y, x - y)\) 。
而后原图上两点的曼哈顿距离就变成切比雪夫距离了。
来理性地证实一波:
假设原来两点为 \((x_1, y_1), (x_2, y_2)\) 变化后就是 \((x_1 + y_1, x_1 - y_1), (x_2 + y_2, x_2 - y_2)\) 。
\[ \begin{align} d_{\mathcal{Chebyshev}} &= \max{\{|(x_1+y_1) - (x_2 + y_2)|, |(x_1 - y_1) - (x_2 - y_2)|\}}\\ &=\max{\{|(x_1-x_2) + (y_1 - y_2)|, |(x_1 - x_2) - (y_1 - y_2)|\}}\\ &=\max{\{|(x_1-x_2) \pm (y_1 - y_2)|\}}\\ &=|x_1 - x_2| + |y_1- y_2| \end{align} \]
注意最后一步能够本身讨论两边的正负来证实。
而后转了后,咱们就能够转化成对于两个点其中一维的差值恰好为 \(D\) ,另一维 \(\le D\) 。
为了方便讨论,咱们先假设 \(x\) 差值为 \(D\) ,另外的一维也是同样讨论。
\[ \begin{cases} x_1 - x_2 = D\\ -D\le y_1 - y_2 \le D \end{cases} \]
咱们固定一维 \(x\) ,那么另一维 \(y\) 就处于一个范围内,咱们就能够快速处理出一个点的度数为多少了。
具体实现就是按 \(x\) 排序, \(x\) 相同按 \(y\) 排序,而后用两个指针 \(l, r\) 维护当前的区间 \([l, r]\) 就好了。(由于区间是单调的)
可是连边确定不能暴力连,但咱们发现是处于一段连续区间内,是否能够线段树优化建边呢?是能够的,但彻底没有必要。
由于最后咱们只须要求联通块,只须要保证连通性不会变,那么每次连边的时候咱们发现相邻的不须要重复连边没有意义,咱们每次记个 \(pos\) 表示当前连边的区间扫到哪了就好了,而后这个点连向最后一个就好了。
这样的话最后的边数是 \(O(n)\) 的了,最后总复杂度是 \(O(n \log n)\) 的,瓶颈在排序上。
曼哈顿距离经常能和切比雪夫距离转化,而后经常定下一维另一个就是个区间范围,这样就好处理不少了。
而后区间连通性连边能够用操做把边数降到 \(O(n)\) 。
戳 这里,挺短的。