Codeforces Round #305 (Div. 2)
C.Mike and Frog(思维+拓展GCD)
•题意
给你初始高度 h1,h2 和目标高度 a1,a2 以及参数 m,x1,y1,x2,y2;
每次操作都可以使得 $h_1=(h_1\cdot x_1+y_1)\ mod\ m $ , $h_2=(h_2\cdot x_2+y_2)\ mod\ m $;
问最少经过多少次操作可以使得 h1 变为 a1 的同时,h2 变为 a2;
•题解
因为涉及取模的操作,所以,一定会有循环节;
任意给定 $2m$ 个数,假设为 $a_1,a_2,\cdots ,a_{2m}$,那么一定有 $\exists \ i,j:\ a_i\ mod\ m = a_j\ mod\ m\ ,i \neq j$;
但因为本题 h 之间都是有联系的,所以,对于 $h_1$ 来说,操作 $2m$ 次,一定会出现循环节;
如果一个循环节中没有出现目标高度 $a_1$,那么,在以后的循环中,一定也不会出现 $a_1$;
但是,$a_1$ 没有出现在循环节中并不代表 $h_1$ 不能变成 $a_1$,因为 $a_1$ 可能出现在循环开始前;
例如,假设 $m=10,h_1=1,a_1=1,x_1=2,y_1=0$;
$h_1$ 的变化如下:
$h_1:1\rightarrow 2\rightarrow 4\rightarrow 8\rightarrow 6\rightarrow 2\rightarrow \cdots$
易得其变化的循环节为:$2\rightarrow 4\rightarrow 8\rightarrow 6$;
而目标高度 1 出现在循环开始前;
当然,题面说了 $a_1 \neq h_1$,这个例子只是说明一下会有 “目标高度出现在循环前” 这种情况;
所以说,目标高度 $a_1$ 可能出现在循环开始前,也可能出现在循环节中,也可能不出现;
这样的话,就得分类讨论;
在紧接着的 $2m$ 次操作中,有如下几种可能:
(1)$a_1$ 未出现或者 $a_2$ 未出现
(2)$a_1$ 和 $a_2$ 都出现在了循环开始前
(3)$a_1$ 出现在了循环开始前,$a_2$ 在循环节中
(4)$a_2$ 出现在了循环开始前,$a_1$ 在循环节中
(5)$a_1$ 和 $a_2$ 都出现在了循环节中
对于情况 (1)、(2)、(3)、(4) 都很好处理,主要是情况 (5) 如何判断是否有解以及如何求出最小的整数解;
下面主要谈谈我对情况(5)的处理;
设 $p_1$ 表示 $a_1$ 第一次出现时进行的操作次数,$p_2$ 表示 $a_2$ 第一次出现时进行的操作次数;
$d_1$ 表示 $a_1$ 所在循环节的长度,$d_2$ 表示 $a_2$ 所在循环节的长度;
判断是否有相同的操作次数,使得 $h_1$ 变为 $a_1$,$h_2$ 变成 $a_2$,可以转化成是否存在 x1,y1 使得等式
$p_1+x_1d_1=p_2+x_2d_2$ 成立;
哇,这不就是拓展欧几里得么;
问题到这就算是搞定了,如果你不会拓展欧几里得算法,可以看一下我的这篇博客(打个小广告,哈哈哈)
•Code
D.Mike and Feet(单调栈)
•题意
有 n 个数,分别表示为 $a_1,a_2,\cdots ,a_n$;
定义 $f_i$ 表示对于任意长度为 i 的连续的区间,都有个区间最小值,求这些区间最小值中的最大值;
输出 n 个数,分别表示 $f_1,f_2,\cdots ,f_n$;
•题解
对于任意一个数 $a_i$,求出以 $a_i$ 为最小值的最大区间,这个可以用单调栈 O(n) 求出;
求出后,按照 $a_i$ 降序排列,优先将 $a_i$ 大的所包含的区间输出;
•Code