1 条题解

  • 0
    @ 2026-5-17 13:07:00

    题意理解

    有一个长度为 nn 的整数数组 aa(下标从 11nn)。
    每次操作:选择下标 ii,将 aia_i 减少 22,并将 a(imodn)+1a_{(i \bmod n)+1} 增加 11
    可以执行任意次操作。
    目标:所有元素变成相等的非负整数
    求最少操作次数,若不可能则输出 1-1


    操作分析

    • 一次操作相当于:aiai2,ai+1ai+1+1a_i \to a_i - 2,\quad a_{i+1} \to a_{i+1} + 1
    • 数组下标是环形的:i=ni = ni+1i+111
    • 总和变化:(2)+(+1)=1(-2) + (+1) = -1 所以每操作一次,总和减少 11

    最终状态分析

    设最终所有数都等于 xxx0x \ge 0 整数),进行了 kk 次操作。
    初始总和 S=i=1naiS = \sum_{i=1}^n a_i
    最终总和:nx=Skn x = S - k

    所以:

    k=Snxk = S - n x

    k0    nxSk \ge 0 \implies n x \le S

    目标:最小化 kk,即最大化 xx(因为 SSnn 固定)。


    可行性的关键条件

    f[i]f[i] 表示从位置 ii 传递到 i+1i+1 的操作次数(ii00n1n-1i=n1i=n-1 时传递到 00)。
    注意:每次操作是一次“传递”,所以 f[i]f[i] 就是执行了多少次从 iii+1i+1 的操作。

    对于位置 ii

    • i1i-1 收到 f[i1]f[i-1] 次增加(每次 +1)
    • i+1i+1 送出 f[i]f[i] 次减少(每次 -2)
    • 初始值是 a[i]a[i]

    最终值:

    a[i]+f[i1]2f[i]=xa[i] + f[i-1] - 2 f[i] = x

    这里下标模 nnf[1]f[-1] 就是 f[n1]f[n-1]


    环形递推

    我们有 nn 个方程(i=0,1,,n1i = 0,1,\dots,n-1):

    a[i]+f[i1]2f[i]=xa[i] + f[i-1] - 2f[i] = x

    整理得:

    2f[i]=a[i]+f[i1]x2f[i] = a[i] + f[i-1] - x f[i]=a[i]+f[i1]x2f[i] = \frac{a[i] + f[i-1] - x}{2}

    其中 f[1]=f[n1]f[-1] = f[n-1] 是环形条件。


    求解方法

    我们不知道 xxf[0]f[0],但:

    11. 最大化 xx
    因为 k=Snxk = S - n x 最小化,所以 xx 最大可取 S/n\lfloor S/n \rfloor
    xx 必须使得存在非负整数解 f[i]f[i]

    22. 枚举 f[0]f[0]
    i=1i=1n1n-1 递推:

    f[i]=a[i]+f[i1]x2f[i] = \frac{a[i] + f[i-1] - x}{2}

    需要满足:

    • 分子 0\ge 0
    • 分子为偶数
    • 结果 f[i]0f[i] \ge 0

    33. 环形验证
    最后检查 i=0i=0 的方程:

    a[0]+f[n1]2f[0]=xa[0] + f[n-1] - 2 f[0] = x

    44. 为什么只尝试 f[0]=0f[0]=011
    因为递推中每一步都需要分子为偶数,f[0]f[0] 的奇偶性影响整个环。
    但实际解如果存在,f[0]mod2f[0] \bmod 2 只有两种可能。枚举即可。


    算法步骤

    11. 计算总和 SS22. 令 x=S/nx = \lfloor S/n \rfloor(最大可能的目标值)。 33. 尝试 f[0]=0f[0] = 0f[0]=1f[0] = 1

    • 递推计算 f[1]f[1]f[n1]f[n-1]
    • 若某步出现负数或奇数,则失败
    • 最后检查环形条件 44. 如果成功,总操作次数为:
    k=Snxk = S - n x

    因为 f[i]f[i] 总和正好是 kk55. 否则输出 1-1


    c++实现

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    
    void solve() {
        int n;
        cin >> n;
        vector<ll> a(n);
        ll sum = 0;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            sum += a[i];
        }
    
        // 最大化最终值 target = floor(sum / n)
        ll target = sum / n;
        
        // f[i] 表示从 i 传递到 i+1 的操作次数
        vector<ll> f(n, 0);
        bool ok = true;
    
        // 枚举 f[0] = 0 或 1(奇偶性)
        for (int start = 0; start <= 1; start++) {
            f[0] = start;
            ok = true;
    
            // 递推 f[1] 到 f[n-1]
            for (int i = 1; i < n; i++) {
                ll need = a[i] + f[i-1] - target;
                if (need < 0 || need % 2 != 0) {
                    ok = false;
                    break;
                }
                f[i] = need / 2;
            }
    
            // 检查环形条件
            if (ok && (a[0] + f[n-1] - 2 * f[0] == target)) {
                // 总操作次数 = sum(f[i])
                ll total_ops = 0;
                for (ll x : f) total_ops += x;
                cout << total_ops << "\n";
                return;
            }
        }
    
        // 无解
        cout << "-1\n";
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int t;
        cin >> t;
        while (t--) {
            solve();
        }
    
        return 0;
    }
    

    复杂度

    每个测试用例 O(n)O(n),总 nn 不超过 2×1052\times 10^5,可通过。


    举例验证

    33
    a=[2,1,2,6]a = [2,1,2,6]n=4n=4
    S=11S = 11x=11/4=2x = \lfloor 11/4 \rfloor = 2

    尝试 f[0]=0f[0]=0

    • f[1]=(1+02)/2=1/2f[1] = (1+0-2)/2 = -1/2 不行。

    尝试 f[0]=1f[0]=1

    • f[1]=(1+12)/2=0f[1] = (1+1-2)/2 = 0
    • f[2]=(2+02)/2=0f[2] = (2+0-2)/2 = 0
    • f[3]=(6+02)/2=2f[3] = (6+0-2)/2 = 2

    检查环形:a[0]+f[3]2f[0]=2+22=2a[0] + f[3] - 2f[0] = 2 + 2 - 2 = 2

    总操作数 k=1+0+0+2=3k = 1+0+0+2 = 3,输出 33,与题目一致。


    总结

    • 每次操作总和减 11,最终值 xx 越大操作次数越少。
    • 最大化 x=S/nx = \lfloor S/n \rfloor 尝试。
    • 转化为环形递推,枚举 f[0]f[0] 的两种奇偶性。
    • 验证非负整数解即可。
    • 1

    信息

    ID
    6649
    时间
    1000ms
    内存
    256MiB
    难度
    1
    标签
    递交数
    1
    已通过
    1
    上传者