EZOJ 刷题笔记(1)

EZOJ65 A

AC code

当 $p_i=i$ 时强制让 $p_i$ 与 $p_{i+1}$ 交换,这样交换显然是对的并且是最优的。

注意当 $i=n$ 时也要这么做因为你可以找到一个 $p_i (1\leq i<n)$ 与 $p_n$ 交换。

时间复杂度为 $O(n)$。

EZOJ20 ymh喜欢函数

AC code

二分神题,最优选择的答案一定是一个下凸函数,所以先特判掉 $t=0$ 的情况是否可行,然后再二分求 $t$ 即可。

若 $t=0$ 时答案小于 $S$,则函数单调下降的部分小于 $S$,二分的区间一定会缩小到函数单调上升的部分,故二分是正确的。

注意出题人卡了 $\log^2$ 做法,找前 $k$ 大时不能用 sort 要用 nth_element,注意 $\sum_i k_it+b_i$ 可能会爆 long long。

这道题实际上数据保证了 $t$ 在 $[0,10^9]$ 范围内必定有解但是并没有说……

时间复杂度为 $O(n\log{V})$。

EZOJ22 ymh的序列

咕咕咕~

EZOJ45 SKY_magician的完全图

AC code

设 $f_{i,j}$ 表示 $i$ 个点的完全图划分成 $j$ 个连通块的方案数,$g_i$ 表示 $i$ 个点的完全图删若干条边的方案数,则有:

$f_{i,j}=\sum\limits_{k=1}^{i-1}\dbinom{i-1}{k-1}\times f_{k,1}\times f_{i-k,j-1} (j\geq 2)$

$g_i=2^{\frac{i\times (i-1)}{2}}$

$f_{i,1}=g_i-\sum\limits_{j=1}^{i-1}\dbinom{i-1}{j-1}\times f_{j,1}\times g_{i-j}$

上述状态转移方程并不难理解,提示:为防止重复计算方案,选取一个关键点,并选择其他一些点连向该关键点构成一个连通块。

最终的答案即为 $f_{n,m}$,注意到题目要求至少删一条边,所以 $m=1$ 时要将一条边都不删的情况给减去。

时间复杂度为 $O(n^3)$。

EZOJ50 SKY_magician的集合

AC code1

AC code2

注意到 $a_i$ 最大才只有 $10^6$ 也就是说枚举因子 $O(V\log V)$ 是能过的。 

设集合中有 $cnt_i$ 个数是 $i$ 的倍数,则答案很显然是 $\sum_i [\forall j\neq i\land i\mid j, cnt_i\neq cnt_j]$。

因为只要存在一个不满足该条件的 $j$,则 $j$ 就可能成为某几对数的最大公因数,$i$ 就一点都不可能了。 

AC code1 是我一开始写比较暴力的 $O(n\log{n}+n\sqrt{V}+V\log{V})$,但是由于 $n$ 和 $V$ 比较小就冲过去了。

AC code2 是此题的正解,时间复杂度为 $O(n+V\log{V})$。

EZOJ127 SKY_magician的qwq

AC code1

AC code2

把 w 看成 $0$,把 q 看成 $1$,问题等价于求长度为 $n$ 的 01 序列满足任意两个 $1$ 中间至少有 $k$ 个 $0$ 的个数。

这个问题就很简单了,可以考虑 DP 也可以考虑组合数去计算。

设 $f_i$ 表示考虑前 $i$ 位且第 $i$ 位是 $1$ 的合法 01 序列方案数,则有:

$f_i=1(0\leq i\leq k)$

$f_i=\sum\limits_{j=0}^{i-k-1}f_j$

上面的那个 $\sum$ 显然可以记录前缀和来优化掉,AC code1 是这种做法,时间复杂度为 $O(n)$。

或者我们也可以把它看成组合数问题,至少有 $k$ 个 $0$ 在两个 $1$ 中间,那么就可以把这些 $0$ 都删去。

所以我们可以枚举有 $i$ 个 $1$,原问题就相当于在 $n-(i-1)k$ 个位置里面放 $i$ 个 $1$ 的方案数,即为:

$\sum\limits_{i=0}^{m}\dbinom{n-ik+k}{i}$,其中 $m=\lfloor\dfrac{n+k}{k+1}\rfloor$ 表示 $i$ 的上界(由 $n-(i-1)k-i\geq 0$ 推导得到)。

注意模数 $5000011$ 是个质数,可提前预处理出阶乘及其逆元,AC code2 是这种做法,时间复杂度为 $O(n)$。

EZOJ51 黎曼函数

AC code

按照题意模拟,预处理出 $f(x)$ 的 $k$ 阶导函数即可。

注意模数是 $10^8+7$ 不是 $10^9+7$。

时间复杂度为 $O(kn+qn)$。

EZOJ52 树状数组套splay

AC code1

AC code2

离线做法很简单,将边权和询问都从大到小排序后,向图中不断加边,用并查集维护当前图中的连通块数即可。

如果强制在线呢?也不难想到选择边权尽量大的边答案一定不劣,所以直接 kruskal 找出最大生成树,保证能让最小的边的边权尽量大,然后对于每次询问二分出最多能用多少条边即可。

注意题目中没有保证图连通,这里所说的最大生成树不一定是连通的,所以设二分出能用 $k$ 条边,答案应为 $n-k$,与最大生成树的边数无关,然而 std 的柿子与边数有关便挂了,这里给出一组 hack 数据:

4 2 1
1 2 1
2 3 2
1

答案应该是 $2$,输出 $1$ 的是错的。

但是我发现出题人造的数据都是一棵树,所以也有可能数据保证图连通但是出题人没有写在题面上?

数据范围说好的 $n\le 10^5$,不知道为啥出题人造的数据 $n$ 最大才 $10^4$,导致在线做法跑得要比离线的快一些。

AC code1 是离线算法,时间复杂度为 $O(m\log{m}+q\log{q}+m\alpha(n))$。

AC code2 是在线算法,时间复杂度为 $O(m\log{m}+q\log{n}+n\alpha(n))$。

EZOJ53 SG函数

AC code

首先 $\dbinom{n}{m}$ 显然比 $\dbinom{n-1}{m}$ 要大,所以我们可以维护一个堆,每次贪心选最大的组合数。

现在难点在于如何比较两个组合数的真实大小,由于数字巨大没法存储真实数字,取模意义下显然也不对,所以可以考虑取对数:

$\log{\dbinom{n}{m}}=\log{\dfrac{n!}{m!(n-m)!}}=\log{n!}-\log{m!}-\log{(n-m)!}$

而 $\log{n!}=\sum\limits_{i=1}^{n}\log{i}$,所以我们存储 $\log$ 函数的前缀和即可,膜意义下的组合数可以提前预处理出阶乘及其逆元。

注意 $\log$ 要用浮点数存,需要 cmath 库里面的 $\log$ 函数。

虽然我用 pb_ds 的配对堆,ext/pb_ds/priority_queue.hpp 库包含了 cmath 库,但是还是建议用 $\log$ 函数就开 cmath 库。

时间复杂度为 $O((n+k)\log{(n+k)})$。

EZOJ57 主席树优化最小割

AC code

一开始打表发现了答案是斐波那契数列,直接矩阵快速幂求解即可,现在来证明一下:

$x\oplus 3x=2x$ 即为 $x\oplus 2x=3x$,而 $x+2x=3x$ 也成立,显然只有当 $x+2x$ 不进位时两个柿子才同时成立。

考虑到 $2x$ 就是 $x\ll 1$,所以 $x+2x$ 进位当且仅当 $x$ 在二进制表示下有相邻的 $1$。

于是就可以设 $f_{i,0/1}$ 表示没有相邻的 $1$ 且最后一位是 $0/1$ 的 $i$ 位二进制数,则有:

$f_{i,0}=f_{i-1,0}+f_{i-1,1}$

$f_{i,1}=f_{i-1,0}$

然后我们把第二个柿子变成 $f_{i-1,1}=f_{i-2,0}$ 并将其带入到第一个柿子中,省略掉第二维,可以得到:$f_i=f_{i-1}+f_{i-2}$。

这也就是斐波那契数列的柿子,证毕。

时间复杂度为 $O(\log{n})$。

posted @ 2021-11-05 07:41  jhqqwq  阅读(129)  评论(0编辑  收藏  举报