本文主要是介绍环上k划分的和的gcd的最大值【gcd基本性质的利用】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
今早看到的题,想了下会做了,但是觉得这题挺有意思的,于是打算写一下做法。本题利用了gcd的基本性质:更相减损法以及结合律,平时做gcd的题基本没用到过这两性质,而本题对这性质进行了充分利用。
思路:
首先我们考虑给一个序列,我们该怎么做。
令 fn=∑ni=1ai 。
我们考虑序列的一个 k+1 划分 fx1,fx2−fx1,fx3−fx2,...,fn−fxk ,记为 {x1,x2,x3,...,xk−1,xk} 。
令 A=fx1,B=fx2−fx1,C=fx3−fx2 。
现在我们有 gcd 的两条基本但十分重要的性质:
1. gcd 本质是更相减损法,即 gcd(A,B−A)=gcd(A,B) 。
2. gcd 满足结合律,即 gcd(gcd(A,B),C)=gcd(A,gcd(B,C)) 。
gcd(A,B-A,C-B)=gcd(gcd(A,B-A),C-B)=gcd(gcd(A,B),C-B)=gcd(A,gcd(B,C-B))=gcd(A,gcd(B,C))=gcd(A,B,C)
根据数学归纳法,可以得出结论:序列上的任意一个 k+1 划分 {x1,x2,x3,...,xk−1,xk} 等价于 gcd(fx1,fx2,fx3,...,fxk,fn) 。
因为序列的任意一个划分总是包含 fn ,因此答案一定是 fn 的约数。
接下来,考虑枚举 gcd 的值 g (即枚举答案,
了解了链上的做法,接下来考虑环上的做法。
考虑环上的断点为
现在考虑将断点向右移动 x 单位,即
然后枚举 gcd 的值 g ,然后计算
为了加速这一过程,考虑先枚举
其实无需真的枚举断点,换个角度思考,枚举断点等价于枚举
既然知道是什么原理了,最后总结一下做法:
1.枚举 gcd 的值 g ,
2.令
3.对 b数组 排序,然后统计相同的值出现的次数,
4.初始化 ans[] ,令值全为1,
5.假设值为 x 的出现了
6.对 ans 更新得后缀最大值。
for ( int i = n ; i >= 1 ; --i ) {ans[i-1] = max ( ans[i - 1] , ans[i] ) ;
}
7.第 i 行输出
这篇关于环上k划分的和的gcd的最大值【gcd基本性质的利用】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!