Codeforces Round #305 (Div. 2)

 

传送门

 

 

C.Mike and Frog(思维+拓展GCD)

•题意

  给你初始高度 h1,h和目标高度 a1,a以及参数 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

  CodeForces548C.cpp

 


 

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

  CodeForces548D.cpp

 

posted @ 2019-09-19 17:22  HHHyacinth  阅读(184)  评论(0编辑  收藏  举报