「Round C10 B」间隔 题解

发布时间 2023-10-08 19:47:07作者: 啊鸧仓_Eliauk

简要题意

本题有 \(T\) 组数据。

给定一个由 \(n\) 个元素构成的正整数数列 \(a_1,a_2,a_3...a_{n-1},a_n\)

问至少需要插入多少个整数才能使得 \(a\) 的各相邻元素之差相等(不能插入在头尾)。

\(a\) 数列保证是单调不减的。

\(1 \le n \le 10^6,0 \le a_i \le 10^6,1 \le T \le 10\)

思路

一眼数学题,手玩样例。

4
3 7 11 19

对于上面的数据,可以得到各相邻元素差值为 4 4 8

明显,可以在 \(11\)\(19\) 之间再插入一个 \(15\),使得相邻元素差值为 \(4\),需要插入 \(1\) 次。

3
3 8 10

同理,可得 5 2,这时没有其他方法,就是让相邻差值为 \(1\)

变成了 \(3,4,5,6,7,8,9,10\) 这样的连续数列,需要插入 \(5\) 次。

观察可以发现,我们寻找最小插入次数,本质是在寻找一个合法的最大差值,

想要让差值合法,那么就要求差值必须是原数列的各项零元素之差的因数。

同时要求最大,那不就是 \(\gcd\) 吗?

接下来就好办了,计算原数列相邻各元素之差的 \(\gcd\)

再计算相邻各元素之差(只有不等于 \(\gcd\) 的才参与计算)除以 $\gcd $ 减一之和,输出即可。

再注意一下部分 \(a_i\) 相等的情况,输出 \(-1\),但是这个地方特别坑,不能单纯判断相邻两个是否相等,

注意是部分 \(a_i\) 相等的情况!

Code

#include<bits/stdc++.h>
using namespace std;
const int N = 1e7 + 20;
int t;
int main(){
    // freopen("interval.in","r",stdin);
    // freopen("interval.out","w",stdout);

    cin>>t;
    while(t --){
        int n,a[N],m,ans = 0;
        vector<int> f;
        cin>>n;
        f.push_back(114514);
        for(int i = 1;i <= n;i ++)
            cin>>a[i];
        bool flag = false,falg1 = true;
        for(int i = 1;i < n;i ++){
            if(a[i] != a[i + 1])
                falg1 = false;
            if(a[i] == a[i + 1])
                flag = true;
        }
        if(flag && !falg1){
            cout<<-1<<endl;
            continue;
        }
        for(int i = 1;i < n;i ++)
            f.push_back(a[i + 1] - a[i]);
        m = f[1];
        for(int i = 2;i < n;i ++)
            m = __gcd(f[i],m);
        for(int i = 1;i < n;i ++)
            if(f[i] != m)ans += f[i] / m - 1;
        // for(int i = 1;i < n;i ++)
        //     cout<<f[i]<<" ";
        // cout<<endl;
        cout<<ans<<endl;
    }
    return 0;
}

后记

啊啊啊啊啊啊好气啊我就是个大S*!!!炒鸡大撒被!!!请无视这个疯子。

考场上时忘了,是部分 \(a_i\) 相等的情况,所以……

我是黑暗傻逼大蒟蒻!请继续忽略这个疯子。