hiho 挑战赛16 B 王胖浩与环

因数,前缀和

题意:
给你一个循环数组,你要将它截成k段,然后每段有一个区间和,所有的区间和求gcd,就是优美程度,你要使得优美程度最大。k不是输入的,而是你要输出截1段,2段...n段的最优值

数据范围:
n<=2000,ai<=5*10^7

思路:

我算了一下,暴力dp要O(n4)...

注意到,这个优美程度肯定是数组所有元素的和的因子(这个不难证明),那么我们可以把问题反转过来考虑,考虑要截出优美程度为因子x,最多能截多少段。

这里有个很好的性质就是,因子x能截y段,那么就肯定能截y-1段,y-2段...因为你可以把其中相邻的两段合起来,这样它们的区间和还是会整除x的

从头到尾地扫,维护sum,当sum能整除x就截。由于是循环数组,这样的话就要枚举开头去截得到的所有答案求个max。这样的话复杂度就是O(n2*d),d是sum的因子数量。由于sum是longlong范围的,因此会出现有些数因子十分多,d就不是常数或者logn这么简单了

我们要优化掉枚举开头这个东西,有一个很重要的结论,区间和整除,就是前缀和同余!因此我们只需要求出前缀和,然后把它们分组,按模因子x的余数分组。然后最大的那个组的size就是因子x的最多能截的段数。

注意到余数可能是很大的,因此不能直接开个数组记录,要哈希一下,或者直接用个map。由于前缀和最多才2k个,因此加个log也没所谓。

我们把每个因子得到的答案都保存下来,输出截k段的时候,我们直接遍历所有因子,然后找截的最大段数>=k的并且值最大的因子输出。最后复杂度是O(nlogn*d)


注意一点,因子越小不意味着能截更多的段数,所以最后那步是遍历所有因子而不是二分什么的


总结:答案肯定是数组和的因子,把问题反转,求每个因子最多能截多少段


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值