2024.08做题记录

1. CF360B Levko and Array

这道题在To do list上躺了好久了。

首先最大值最小,考虑二分答案。

二分这个答案,设其为\(w\),然后怎么判断是否能行?不难想到转移会跟上一个数是多少、第几个数、修改几次有关。可以设\(dp_{i,l}\)表示第\(i\)个数改为\(l\)的最小次数。转移略。

然后\(a_i\le 10^9\),怎么放也不行。

我们发现,对于一段数 \([l,r]\) ,我们将其全部修改( \(l-1\)\(r+1\) 不改),能使改后序列合法的条件是 \(|a_{r+1}-a_{l-1}|\le w\times (r-l+2)\) ,把 \([l,r]\) 的数改成什么不重要。

所以设\(dp_i\)表示第\(i\)个不改的最小操作次数,我们可以枚举前一个未被修改的点,则有转移方程 \(dp_i=\min_{j<i且|a_i-a_j|\le (i-j)\times w}dp_j+i-j-1\)

初始化\(dp_i=i-1\)。表示\([1,i-1]\)全改。

答案为\(\min_{i=1}^{n}dp_i+n-i\)

时间复杂度\(O(n^2\log V)\)

提交记录

2. P7077[CSP-S2020] 函数调用

首先线段树一定超时,但是考场上一般就直接打线段树了。

我们先来看一看加/乘操作的某一位置上的数的影响。

若对 \(5\) 的数 \(+2\)\(\times 3\)\(+7\)\(\times 4\) ,则原式为\(((5+2)\times 3+7)\times 4=5\times 3\times 4+2\times 3\times 4+7\times 4\)

可以发现,每一次加法对于最终答案的贡献为从当前到最后所有乘数的积再乘上加的值。

把所有操作全部倒序进行,先建出图来,然后设 \(0\) 号节点为主操作向下连边。

然后按照顺序考虑如何维护出每个节点以后的所有乘数的积。考虑拓扑排序。

对于每个节点,先建反图跑一遍拓扑排序,维护出 \(mul\) 数组,表示若执行一次这个操作会使全部的数乘上多少。

最后再正向跑一遍拓扑排序,记\(cnt_i\)数组为 \(i\) 号操作的对最终答案的和,这里不是 \(1\) 类操作的操作我们也要把它记下,用来对出它的子操作的调用值。

具体来说,设 \(arr_i\) 表示 \(u\) 号操作的倒序的第 \(i\) 个子操作,则有 \(cnt_{arr_i}\gets cnt_u\times \Pi_{j=1}^{i-1}mul_{arr_j}\)

最终对于所有的 \(1\) 类操作,对应的位置的答案增加 \(w_i\times cnt_i\) ,其中 \(w_i\) 为要加的值。

然后该题目有以下坑点:

  1. \(998244353\) 取模。(罚时 \(\times 2\)
  2. 为了避免把没有调用的答案算进去,第二次拓扑排序的队列里的初始元素只能有\(0\)。(罚时 \(\times 3\)
  3. 但是只这样做可能导致有些点的入度减不完,也就入不了队,所以还得先从 $ 0 $ 号节点遍历一遍所有点,初始化入度数组。(罚时 \(\times 3\)

提交记录

3. AT_arc050_c LCM 111

首先发现\(111111\)型的可以拆成\(10101\times 11\)这种类型,然后考虑刚才的拆法后面那个全为\(1\)的因子,不难发现,最长为\(\gcd (A,B)\)

现在两个数除以那个公因数后一定互质,设\(a\)为长度为\(A\)的全为\(1\)的数,\(b\)为长度为\(B\)的全为\(1\)的数,\(c\)为$\gcd (A,B) $位的全为\(1\)的数,则答案为\(\frac{a}{c} \times \frac{b}{c}\times c\)

然后发现\(A,B\le 10^{18}\),直接算完全不行。

考虑矩阵快速幂优化。先考虑怎么算 \(c\) 。发现长度为\(i\)的全为\(1\)的数有递推式\(f_i=f_{i-1}\times 10+1\)。写成矩阵有:

\(\begin{bmatrix} 10 & 1 \\ 0 & 1 \end{bmatrix}\times \begin{bmatrix} f_{i-1} \\ 1 \end{bmatrix}=\begin{bmatrix} f_i \\ 1 \end{bmatrix}\)

直接矩阵快速幂即可。

对于\(\frac{a}{c}\)\(\frac{b}{c}\),类似地有:

\(\begin{bmatrix} 10^{\gcd(A,B)} & 1 \\ 0 & 1 \end{bmatrix}\times \begin{bmatrix} g_{i-1} \\ 1 \end{bmatrix}=\begin{bmatrix} g_i \\ 1 \end{bmatrix}\)

中间这个\(10^{\gcd(A,B)}\)可以用快速幂求。

最终时间复杂度\(O(\log V)\)

注意,矩阵乘法不具有交换律,写矩阵快速幂时注意不要写反!

提交记录

4. CF1034A Enlarge GCD

显而易见,先把所有数都除以它们的\(\gcd\),然后找到最大的\(k\)使得\(w=\sum_{i=1}^{n}[a_i\equiv 0(mod\ k) ]\),答案为\(n-w\)

对于每一个数进行质因数分解,把对应的质因子\(num\)数量加\(1\),最后找最大的\(num\)值的质因子。

直接分解在\(a_i\le 1.5\times 10^7\)过不了,时间复杂度\(O(a_i\sqrt{a_i})\)。考虑用线性筛预处理出每个数的最小质因子然后直接不断跳。时间复杂度\(O(V+a_i\times a_i的质因子个数)\)。这个值比\(O(a_i\ln a_i)\)小,可以过。

提交记录

5. AT_arc126_c Maximize GCD

首先注意到当\(k\ge n\times \max a_i\) 时我们可以把所有数填成一样的,这样他们的\(\gcd\)一定是最优的。

这样对于剩下的情况,就一定有 \(答案\le 3\times 10^5\),然而对于每一个\(\gcd\),他需要的 \(k\) 并不单调,不能用二分,所以考虑直接枚举。

然后以上就是我自己的思考。

接下来对于每一个枚举的数\(d\),代价为 \(\sum_{i=1}^{n}(d-a_i\ mod\ d)\),转化一下就是\(nd-\sum_{i=1}a_i\ mod\ d\)。怎么去找后面这个呢?

我们记 \(t_i\)\(i\)\(a\) 数组里的出现次数,维护 \(num_i\)\(1\sim i\) 的数在 \(a\) 数组里的出现次数和,记 \(sum_i=\sum_{j=1}^{i}j\times t_j\)

然后枚举k,则在 \((kd-k,kd]\) 区间内的每一个数\(mod\ d\) 的值都为 \(a_i-(k-1)\times d\) 。所以这一段的答案为 \(sum_{kd}-sum_{kd-k}-(k-1)\times d\times (num_{kd}-num_{kd-d})\)。最后对每一段类似地进行计算。

运算次数为 \(\frac{n}{1}+\frac{n}{2}+\frac{n}{3}+...+\frac{n}{n-1}+\frac{n}{n}\) ,小于 \(n\log n\)

提交记录

6. AT_abc161_f Division or Subtraction

简单题。

如果 \(k\) 合法就两种情况:

  1. \(n\equiv 1(mod\ k)\)
  2. \(k^d|n \ \ (d>1)\)\(\frac{n}{k^d}\equiv 1(mod\ k)\)

对于第一种,直接就是 \(n-1\) 的因数个数;对于第二种,枚举 \(n\) 的因数,然后直接暴力判断。

时间复杂度\(O(\sqrt V\log V)\)左右。

提交记录

7. P5502 [JSOI2015] 最大公约数

类似取模,每一次更新 \(gcd\) 的值一定有\(\gcd'\le \gcd\)

所以每一次更新后的\(\gcd'\neq\gcd\)则一定有\(\gcd'\le \frac{1}{2}\gcd\),所以最多会存在 \(\log a_i\)个不同 \(\gcd\)。考虑固定右端点,维护一个队列,里面的每一个 $u $ 保证 \(\gcd\{u,u+1,u+2,...,i\}\)互不相同,此时队列里的元素个数一定小于\(\log a_i\)且单调递增。然后再往下更新。

如果在更新过程中发现相邻的数更新后的 \(\gcd\) 相同,则不把后面的数加入,因为前面的数一定更优。

时间复杂度\(O(n\log n)\)

提交记录

8. AT_abc191_f GCD or MIN

\(\min\) 操作,受到P8321 沈阳大街 2AT_agc030_f Permutation and Minimum的影响,相当于就是说把 $ a $ 从小到大排序。然后从小到大遍历,对于每一个 $ i $ 可以选择将其删去(与前面的某个数取 $ \min $ )或与前面的某几个取 $ \gcd $。

再考虑最终剩下的数,发现一定小于等于 $ \min a_i $

想起上一道题的 $ \gcd $ 结论,则最多会有 $ n\log n $ 个不同的 $ \gcd $ 值。所以开一个 $ set $ ,每一次把 $ a_i $ 与 $ set $ 里的值取 $ \gcd $ 再放入 $ set $ , $ set $ 里之前的元素不删去(因为可以让 $ a_i $ 不进行 $ \gcd $ 操作)。

最后再找出 $ set $ 中小于等于 $ \min a_i $ 的元素个数。

但这样做是 $ O(n^2\log n\log V) $ 。过不了乐。

怎么优化?发现 $ set $ 有一个功能是排序,而这个功能我们不需要,我们只要能去重就行。考虑用 $ bitset+vector $ , $ bitset $ 用于判断 $ vector $ 里是否有这个元素, $ bitset\ 10^9 $ 开的下。

最后再扫一遍 $ vector $ ,记录小于等于 $ \min a_i $ 的元素个数。

然后就可以艹过去,喜提最慢解。

时间复杂度\(O(\frac{n^2\log V}{w})\)

提交记录

9. CF1646E Power Board

最初想法是对于每一行,求出有多少个数是上方的行里没有出现的,写了一发。然后WA了。

看了正解,将幂运算转化为对数运算。我们可以将行编号为 \(\{d,d^2,d^3,...,d^k\}\)放在一起考虑,这样我们就有一个统一的底数了。

然后将\((d^k)^n\)换成 \(k\times n\) ,这样的话我们只用对\(\{1\times 1,1\times 2,1\times3,...,1\times m, 2\times 1,2\times 2,...,2\times m,...,k\times 1,k\times 2,k\times 3,...,k\times m\}\)进行去重求个数。然后对于相同的 \(k\) ,它的贡献一定相同,且与\(d\)无关。

这样为什么对呢?我们担心一个数会被 \((d^m)^n\)\((d^n)^m\)算两次,但其实,以上的两个数都被\(d\)算过了且打过标记了,不会再作为新的底数计算答案。

时间复杂度 \(O(m\log n+n)\)

提交记录

10. CF1497E Square-Free Division

首先先看简单版。

我们知道判断一个数是不是完全平方数,看的是质因子的指数是否全是偶数。

\(k^d|a_i\)\(k^{d+1}\nmid a_i\)所以我们可以把a_i的所有的质因子k进行一下操作:

  1. \(2|d\),则\(a_i\gets \frac{a_i}{k^d}\)
  2. 否则,\(a_i\gets \frac{a_i}{k^{d-1}}\)

这样,剩下的数的质因子的指数都是奇数。用线性筛预处理,再分解质因数,时间复杂度\(O(V+n\ln n)\)

那么我们只用判断是否有两个数相同就行了。

看复杂版,现在带修改了。

我们考虑dp,可以考虑设\(dp_{i,k}\)表示 $[1,i] $ 区间修改 \(k\) 个的最小的区间个数。然后我们有两种方案转移:

  1. 枚举上一个修改的位置,则有 \(dp_{i,k}=\min_{j=1}^{i-1}dp_{j,k-1}+[j+1,i]新增块数\) 。然后发现新增块数不好求,遂放弃此算法。
  2. 找上一块的最后一个位置\(j\),将\([j+1,i]\)分为一块。这里我们可以枚举\(x\),表示\([j+1,i]\)至少要\(x\)次修改才能变成一块,找到最左端的\(j\)使得满足上面的要求,记为\(pos\),然后就有\(dp_{i,k}=dp_{pos,k-x}+1\)

然后继续推算法\(2\),可以处理出\(las_{i,x}\)为最小的\(j\)使得\([j,i]\)最少需\(x\)次修改才能变成一个块。可以发现,当\(i\)增加时,\(las_{i,x}\)一定单调不减,所以可以双指针进行预处理。时间复杂度\(O(kn)\)

然后就是\(dp\)过程,枚举\(k\)\(x\),则可以如上转移,时间复杂度\(O(nk^2)\)

总时间复杂度\(O(nk^2+nk+n\ln n+V)\)

提交记录

11. UVA12716 GCD XOR

\(\gcd(a,b)\)\(a\ xor\ b\)没什么关系,所以考虑找一个中间项把它们联系起来。

首先有\(\gcd(a,b)=\gcd(a,a-b)\),所以一定有\(\gcd(a,b)\le a-b\)

然后找一找\(a-b\)\(a\ xor\ b\)的关系。有以下几种情况:

  1. 二进制一位如果\(a\)\(b\)都是\(1\),则该位\(a-b=a\ xor\ b\)
  2. 二进制一位如果\(a\)\(b\)都是\(0\),则该位\(a-b=a\ xor\ b\)
  3. 二进制一位如果\(a\)\(0\)\(b\)\(1\),则该位\(a-b<a\ xor\ b\)
  4. 二进制一位如果\(a\)\(1\)\(b\)\(0\),则该位\(a-b=a\ xor\ b\)

综上则一定有\(a-b\le a\ xor\ b\),所以连起来即\(\gcd(a,b)\le a-b\le a\ xor\ b\),然后我们要求\(a\ xor\ b=\gcd(a,b)\),所以有\(a\ xor\ b=\gcd(a,b)=a-b\)

\(c=a-b\),枚举\(a\)\(c\),则有\(b=a-c\),我们只用判断是否有\(a\ xor\ b=c\)。因为\(c=\gcd(a,b)\),要更小一些,所以外层枚举\(c\),再枚举\(c\)的所有倍数,即为\(a\)

运算次数为\(\frac{V}{1}+\frac{V}{2}+\frac{V}{3}+...+\frac{V}{V-1}+\frac{V}{V}\)。因为\(b\neq 0\),所以\(a\ge 2\times c\),所以实际运算次数为\(\frac{V}{1}+\frac{V}{2}+\frac{V}{3}+...+\frac{V}{V-1}+\frac{V}{V}-V\approx 5\times 10^8\)4.0s能过。

然后发现每一次询问可以看成一个前缀和形式,所以直接预处理到\(3\times 10^7\),然后\(O(1)\)查询。

提交记录

12. P3861 拆分

忒难了。

看得出来是一道dp题。

然后发现n的因数一定小于\(8000\),所以考虑\(O(n^2)\)做法。

证明待补。

先找出\(n\)的因数,设\(x_i\)为第\(i\)小的因数,设\(dp_{i,j}\)表示将\(x_i\)用不超过\(x_j\)\(x\)的因数进行表示的方案数。则转移为:

\(dp_{i,j}\gets dp_{i,j-1}\)

\(dp_{i,j}\gets dp_{k,j-1}\ \ \ \ \ \ \ \ x_i \% x_k=0\)

待补。

13. AT_abc276_g Count Sequences

现在我们记差分数组\(b_i=a_i-a_{i-1}\),那么题目要求则为\(b_i\equiv 1或2(mod\ 3)\ \ i\in[2,n]\)\(b_1\equiv 0,1或2(mod\ 3)\)

然后\(b_1\)的条件比较特殊所以我们先不考虑它。

那么设\(d=\sum_{i=2}^{n}[b_i=2]\)\(c=\sum_{i=2}^{n}[b_i=1]\),则有\(c=n-1-d\),那么\(a_n=2d+c+b_1=2d+n-1-d+b_1=n+d-1+b_1\le m\)

所以现在我们会对其中某一些数\(+3\),但为了保证\(a_n\le m\),所以我们最多能进行\(p=\lfloor\frac{m-n-d+1-b_1}{3}\rfloor\)\(+3\)

进行\(p\)\(+3\)操作可以视为当前有\(p+n\)个小球,可以选择\(n\)个,选中的就是原来的\(a_i\),没选中的相当于给后面第一个选中的数\(+3\),类似于差分数组。但是最后一个球一定被选中,所以方案数为\(C_{n+p-1}^{p}\)

然而我们可以不进行\(+3\)操作,只要我们的\(+3\)操作次数\(\le p\)就行了,所以方案数为\(\sum_{i=0}^{p}C_{n+i-1}^{i}\)。这个可以预处理出来。

但是哪一些\(b_i=1\),哪一些\(b_i=2\)呢?这里还需要统计方案数,所以还需乘上\(C_{n-1}^{d}\)

所以外层枚举\(b_1\),内层枚举\(d\),则最终答案为\(\sum_{b_i=0}^{2}(\sum_{d=0}^{n-1} (C_{n-1}^{d}\times \sum_{p=0}^{\lfloor\frac{m-n-d+1-b_1}{3}\rfloor}C_{n+p-1}^{p}))\)

组合数是可以预处理的,时间复杂度\(O(n+V)\)

提交记录

14. CF1978F Large Graph

设矩阵的左上角为\((1,1)\),它下方的格子为\((2,1)\)

发现有\(k\ge 2\),那么对于\(b_{x,y}\neq 1(x,y<n)\)\((x,y)\)\((x+1,y+1)\)一定在同一个强连通分量里,因为\(|x+1-x|+|y+1-y|=2\le k\)

然后发现通过原来的一维数组\(a\)的同一个位置\(x\)上的数循环右移出来的数如果被分成了两个部分,则如果\(k<n+1\)则不可能直接相连。

所以我们可以把一个二维的矩阵拍成一维的数组\(c\),把第一列和第一行连起来。如\(a=\{3,4,5\}\),则\(c=\{4,5,3,4,5\}\)

然后就对这个一维数组从前往后进行扫描,判断每一个位置属于哪一个强连通分量。那么可以先用线性筛筛出来所有质数。然后对\(c_i\)分解质因数,对于每一个质因数,判断它上一个可以整除的位置\(j\)是否有\(|i-j|\le k\),如果有就直接从\(i\)\(j\)连边。

这里我想过很多办法判断是否在同一个强连通分量,以及各个质因数之间的合并问题,但发现我其实想复杂了,其实最简单的方式就是连边,然后遍历所有联通块。

然后每一个数最多向前连它的质因数个数条边,最多是\(n\log a_i\approx 2\times 10^7\),可以开得下。

然后就是矩阵中每一个 $ 1 $ 都会单独在一个强连通分量内,所以答案要加\(n\times \sum_{i=1}^{n}[a_i=1]\)

时间复杂度\(O(tn\ln n+V)\),空间复杂度\(O(n\log n)\)

提交记录

posted @ 2024-09-07 15:31  Twilight_star  阅读(27)  评论(0)    收藏  举报