hihoCoder #1246 王胖浩与环

题目大意

\(n\)\(1\le n\le 2000\))个正整数 \(a_1, a_2, \dots, a_n\)\(a_i\le 5\times 10^7\))分布在一个圆环上。
定义 \(b_k\) 为:将环上的数划分成 \(k\) 段,每段上的数之和的 GCD 的最大值。
\(b_1, b_2, \dots, b_n\)

解法

首先,不难看出, \(b_k\)\(n\) 个数之和 (记做 \(S\))的约数。
考虑到 \(S\) 的约数并不多(\(2\sqrt{n}\) 是很松的上界,并且往往 \(n\) 越大这上界越松),从而可以考虑枚举 \(S\) 的约数 \(d\),问题转化为

\(n\) 个数最多能分成几段,使得每段数之和都能被 \(d\) 整除。

算法一

枚举分段的起始位置 \(i\),以 \(i\) 为序列起点求前缀和,看前缀和中有几个能被 \(d\) 整除。
复杂度 \(O(n^2)\)

算法二

不必枚举分段的起点。
对输入序列求前缀和。
按模 \(d\) 的余数将 \(n\) 个前缀和分类,用 std::unordered_map<int,int>,记录每个类中有多少个前缀和。
最大的类的 size 即为所求。

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

这个做法应该是老套路了,我却不知道,我太菜了。TAT

posted @ 2018-02-03 12:14  Pat  阅读(164)  评论(0编辑  收藏  举报