1 条题解

  • 0
    @ 2026-7-18 21:21:40

    多好的一道思维题!

    蒟蒻觉得大佬们双指针贪心部分讲得有些简略,故写一篇题解来具体说说自己的想法。

    首先,我们要发现一个重要的性质:记最终的答案为 ansans,那么 ansans 一定整除 i=1nAi\sum_{i=1}^{n} A_i。因为无论怎么操作序列的和都不变,且最后必须保证 ansans 是所有 AiA_i 的公约数。

    那么,我们记 sum=i=1nAisum=\sum_{i=1}^{n} A_i,则 ansans 一定是 sumsum 的因子。那就需要枚举 sumsum 的因子,合法的最大因子就是 ansans

    接下来就是判断是否合法。当考察因子 xx 时,考虑记录每个 Bi=AimodxB_i=A_i \bmod x,并将它们从小到大排序,接着进行双指针扫描,贪心地计算所需操作次数 cntcnt,若 cntkcnt\le k 则合法。记左指针为 ll,右指针为 rr,具体贪心实现如下:

    • Bl+Br=xB_l+B_r=x,那么操作 BlB_lBl,BrB_l,B_r 就可以都变成 00cntcnt 加上 BlB_l,两个指针都向中间靠 11 个坐标。

    • Bl+Br<xB_l+B_r<x,那么钦定操作 BlB_l 次使得 BlB_l 变成 00,则 BrB_r 变成 Br+BlB_r+B_lcntcnt 加上 BlB_l,左指针向中间靠 11 个坐标。

    • Bl+Br>xB_l+B_r>x,那么钦定操作 xBrx-B_r 次使得 BrB_r 变成 xx,相当于变成 00,则 BlB_l 变成 Blx+BrB_l-x+B_rcntcnt 加上 xBrx-B_r,右指针向中间靠 11 个坐标。

    如果你对后两个操作有疑问,如“为什么要这样钦定”,请代入前提条件“已经将 BiB_i 从小到大排序”。

    那么本题就完成了,时间复杂度是 O(nlognsum)O(n\log n\sqrt {sum})。但实际上肯定要比这个快,因为 O(nlogn)O(n\log n) 是检查因数时排序的复杂度。

    #include <bits/stdc++.h>
    #define i64 long long 
    const int N = 505; 
    using namespace std;
    int n, k, a[N]; 
    i64 sum, ans, b[N]; 
    bool chk(i64 x) {
    	for(int i = 1; i <= n; i++) b[i] = 1ll * a[i] % x; 
    	sort(b + 1, b + n + 1); 
    	int l = 1, r = n; 
    	i64 cnt = 0; 
    	while(l <= r) {
    		if(b[l] + b[r] == x) cnt += b[l], l++, r--; 
    		else if(b[l] + b[r] < x) cnt += b[l], b[r] += b[l], l++; 
    		else if(b[l] + b[r] > x) cnt += x - b[r], b[l] -= (x - b[r]), r--;  
    		if(cnt > k) return false;  
    	} 
    	return cnt <= k; 
    } 
    int main(){
    	scanf("%d %d", &n, &k); 
    	for(int i = 1; i <= n; i++) {
    		scanf("%d", &a[i]); 
    		sum += a[i]; 
    	} 
    	for(i64 i = 1; i * i <= sum; i++) {
    		if(sum % i == 0) {
    			if(i > ans && chk(i)) ans = i; 
    			if(sum / i > ans && chk(sum / i)) ans = sum / i; 
    		}
    	} 
    	printf("%lld\n", ans); 
    	return 0;
    }
    
    • 1

    信息

    ID
    11714
    时间
    2000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    2
    已通过
    2
    上传者