题解 Codeforces Round 885 (Div. 2) / CF1848A~F

https://codeforces.com/contest/1848/

VP 选手 前来报到

A. Vika and Her Friends

https://codeforces.com/problemset/problem/1848/A

Problem

一个 \(n\times m\) 的网格。Vika 和她的朋友们在格子里,他们互相知道彼此的位置。每秒钟,Vika 先移动到相邻格子,朋友在知道 Vika 的位置后也分别移动到相邻格子里,这样以后,Vika 如果与朋友格子重叠,则 Vika 被抓住。Vika 永远都不会被朋友抓住吗?

Solution

考虑 Vika 和其中一个朋友的曼哈顿距离:Vika 走一步,他们的距离要么加一要么减一;朋友也一样。那么每秒后他们的距离,要么不变,要么 \(\pm2\)。那么与 Vika 距离为奇数的朋友,永远抓不到 Vika。与 Vika 距离为偶数的朋友,总能将 Vika 逼到角落将其击杀。

B. Vika and the Bridge

https://codeforces.com/problemset/problem/1848/B

Problem

长为 \(n\) 的木板上染满颜色。你可以再更改一个区域的颜色。然后选择一些颜色相同的区域,使得他们两两间的距离最大值最小(包括两个边界)。\(n\leq 10^5\)

Solution

每种颜色分开讨论。间隔最远的区域,在中间染一次颜色。

C. Vika and Price Tags

https://codeforces.com/problemset/problem/1848/C

Problem

长为 \(n\) 的数列 \(a,b\)。每秒钟进行这样一次操作:

  • 构造 \(c\) 使得 \(c_i=|a_i-b_i|\)
  • \(a:=b,b:=c\)

是否存在一个时刻使得 \(a\) 全为 \(0\)?非负整数数列 \(a_i,b_i\leq 10^9\)\(n\leq 10^5\)

Solution

每一位分开讨论。观察到如果有零,则变化将形如 \(0,a,a,0,a,a,\cdots\),以三为一个循环,这启发我们。另一个启发点在于这个减操作和 \(\gcd\) 过程很像,所以最后这个重复的 \(a\) 其实是 \(\gcd\)

那么我们尝试优化这个 \(\gcd\) 的过程。

int solve(int x,int y){//最终的 0 出现在哪里
	if(!x) return 0;
	if(!y) return 1;
	if(x<=y) return solve(y,y-x)+1;//+1 表示位移一下,对上最终的循环
	return solve(y,x-y)+1;
}

现在 \(x>y\)。回想更经常的求 \(\gcd\) 的方法,应该是 \(\gcd(x,y)=\gcd(y,x\bmod y)\),这启发我们用模运算优化最后一步。大概写一下这个数列:

\[x,\boxed{y,x-y},\begin{cases}\boxed{x-2y,y}(x\geq 2y)\\2y-x,\cdots(x<2y)\end{cases} \]

那么可以大概发现就是说减掉奇数个和偶数个 \(y\) 是不一样的,对它小小分讨一下。

int t=x%y,d=x/y;
if(d%2==0) return solve(t,y);
else return solve(y,t)+1;

最后想使得整个数组都是 \(0\),必须保证它们最终的循环节叠在一起。\(0,0\) 开局的请丢掉。

D. Vika and Bonuses

https://codeforces.com/problemset/problem/1848/D

Problem

有计数器 \(s\geq 0\),输入给定初值。执行以下二选一个操作,重复 \(k\) 次:

  • \(s:=s+(s\bmod 10)\)
  • 获得 \(s\) 的收益。

使得收益总和最大化。\(s,k\leq 10^9\)

Solution

发现 \(s:=s+(s\bmod 10)\) 这个操作,如果只看 \(s\bmod 10\)(就是个位),那么它有循环节。不妨拎出单独考虑。

其中 2,4,8,6 明显是环,1,3,7,9 能一步到环,5,0 是孤独的。

另外一个观察是:我们总会先做操作一再做操作二。于是分类讨论:

  • 全部都是收益。
  • 用一个操作一,然后全部都是收益。5,0 到这里可以停止。

剩下的可以走好多次,我也说不好怎么样更优。因为环的长度为 4,我们按模四分类:

  • 进入环后,用 \(4x\) 次操作一,剩下的全点操作二。
  • 进入环后,用 \(4x+1\) 次操作一,剩下的全点操作二。
  • 进入环后,用 \(4x+2\) 次操作一,剩下的全点操作二。
  • 进入环后,用 \(4x+3\) 次操作一,剩下的全点操作二。

我们可以就是在外面动态维护当前可以用的操作次数 \(k\),在进入环的基础上,先跑一遍,然后 \(k\) 减一,\(s:=s+(s\bmod 10)\),又跑一遍,重复共四次。这样明显可以。

那么怎么求最大值?考虑将答案写出来:(这个 \(k\) 被改过了,理论上来说应该加角标的,但我不管)

\[ans=(k-4x)(s+20x)=-80x^2+(20k-4s)x+ks,\text{where } 0\leq 4x\leq k \]

开口向下的二次函数,激动人心的求导时刻。那么我们对它求导,找出导数的零点(也就是 \(-\frac{b}{2a}\))即最大值取值 \(x_0\),取 \(x_0\) 附近的几个答案和 \(f(0),f(k/4)\),注意定义域。

E. Vika and Stone Skipping

https://codeforces.com/problemset/problem/1848/E

Problem

给定 \(X\)。有多少个正整数对 \((x,y)\) 使得 \(x\leq y\)\(\sum\limits_{i=x}^y=X\)?询问好多次,先给一个 \(X_0\leq 10^9\),然后告诉你 \(\frac{X_i}{X_{i-1}}\)(小于 \(10^6\) 的正整数),对所有 \(X_i\) 分别求出答案,还有对质数取模。

Solution

不妨先将 \(X\) 翻倍,去掉求和公式里面一个很烦的 \(\frac{1}{2}\)

\[2\sum\limits_{i=x}^y=2\sum\limits_{i=1}^y-2\sum\limits_{i=1}^{x-1}=y(y+1)-x(x-1)=y^2+y-x^2+x=(x+y)(y-x+1)=2X. \]

这启发我们对 \(2X\) 分解因数。观察到:\((x+y)+(x-y+1)=2x+1\) 是个奇数,这要求我们的这一对因数的和要是奇数。而且一对因数唯一对应一个 \((x,y)\)

我们分解的竟然是 \(2X\),不妨把所有 \(2\) 放在一边,选择一些奇数质因子放在另一边。那么我们终于看出方案数是 \(\prod_{x\neq 2}(cnt_x+1)\) 其中 \(cnt_x\)\(2X\) 的唯一分解的出现次数。

这个东西怎么维护呢?这个模数可能很小,可能没有逆元。所以用线段树维护。

F. Vika and Wiki

https://codeforces.com/problemset/problem/1848/F

Problem

数列 \(a\) 下标从零开始,长度 \(n=2^k\leq 2^{20}\),值域 \([0,2^{30})\)。每秒钟进行一次操作:所有数字同时 \(a_i:=a_i\oplus a_{(i+1)\bmod n}\)(异或)。求什么时候整个数列清零。我们可以证明方案一定存在。

Solution

先按位拆分手完几个:\(01010101\) 可以两步。我们可以考虑做两次操作意味着什么:(o 表示取这些数字的异或和)

0:o
1:oo
2:o o
3:oooo
4:o   o
5:oo  oo
6:o o o o
7:oooooooo

竟然是分形,又因为一个全零的数列再做操作没啥意义,我们想到二分求这个东西。但是我们似乎求不出来某一行。但是我们能求出 \(2^k-1\) 行(取 \(2^k\) 个数)进一步 \(2^k\) 也可以(甚至更简单),所以倍增。发现惊人事实:这玩意不用按位处理。同时证明不可能无解:第 \(n\) 秒时因为取模,所有数字需要的那两个点重合,所有数字都是零。\(O(n\log n)\)代码真的很优美

以下更新:

@Morning_Glory
呃我可能说的不好,大概是说你分析两次操作对应原数列哪些数字异或,三次是哪些,四次是哪些,最后发现它像一个杨辉三角的图形,而且第 \(2^j\) 行(即 \(2^j\) 次操作)对应原序列 \(i,i+2^j\) 两个位置的数字的异或和。又因为一个全零数组再操作也是全零,所以使用倍增算法,快速计算进行 \(2^j\) 次操作后序列的样子,然后更新一下指针。证明一定有解是注意到 \(n=2^k\),当进行 \(2^k\) 次操作时刚好会因为取模把要用的两个数重叠变成 \(0\),从而变成全零的数组。

这个重要结论也可以通过暴力展开,或者用 \(2^{j-1}\)\(2^{j-1}\) 归纳证明。

这边 看到一个神奇优化可以线性,就是说搞完一次后数组前后两半是一样的,只用做其中一半就行了。不知道对不对?因为有的倍增点是不用的啊。我不知道。

Codes

posted @ 2023-07-17 13:46  caijianhong  阅读(545)  评论(5编辑  收藏  举报