CF 1100~1500 数论
GCD Partition
题意:
给定长度为 \(n\) 的数组 \(a\)。
要求把它分成 \(k(1\lt k\le n)\) 个子段,要求所有子段和的最大公约数最大,求这个最大值。
设 \(l_i,r_i(1\le l_i \le k)\) 分表示第 \(i\) 个子段的左右端点。这个子段的子段和 \(b_i=\sum\limits_{j=l_i}^{r_i}a_j\)。
要求 \(l_i\le r_i\),对于所有 \(1\le j\lt k\),有 \(l_{j+1}=r_j+1\),并且 \(l_1=1,r_k=n\)。最大化 \(\gcd(b_1,b_2,...,b_k)\)。
分析:
由于是对子段求公共GCD,可知子段和是连续的
假设对于一种分段方式中有 n 段,假设此时的公共 GCD 为 k,显然 k 必定满足是所有段和的约数,接下来合并其中两个段,此时的 n - 1 段仍然满足 k 为每段的约数
立即推:分成 2(k > 1)段时,此时的 GCD 最大
code
Make It Round
题意:
给定 \(n\) 和 \(m\), 我们可以把 \(n\) 变为 \(n\cdot k(1\leq k\leq m,k∈N^{*})\), 请输出末尾 \(0\) 的个数最多的 \(n\cdot k\)。
- 例如, \(481000\) 比 \(1000010\) 末尾 \(0\) 的个数更多
- 如果有多个末尾 \(0\) 个数最多的 \(n\cdot k\), 则输出其中最大的一个
- 如果不存在末尾 \(0\) 个数更多的 \(n\cdot k\), 则输出 \(n\cdot m\)
分析:
对于给定的\(n\),若要在末尾产生\(0\),则必须通过与本身因数中的\(2\)或\(5\)相乘或者直接乘\(10\)获得
所以应当尽量先消耗\(2\)和\(5\)的个数(在\(m\)的范围内取对应的数),最后要保证数尽量的大,所以在取完\(2,5,10\)之后检查是否能继续乘上一个数使数增大