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