1 条题解

  • 0
    @ 2024-10-12 21:01:41

    思路

    贪心+二分

    根据题意我们可以对数组aa做任意次操作,去求最大的mexkmex_k,因为k的值是固定的,所以我们尽量让数组aa的值变小,小到k可以覆盖他,这样就可以最大限度的增大mexkmex_k的值

    所以我们的有效操作就是让 ai=aiaj(ajai)a_i = a_i -a_j (a_j \le a_i ),操作累加起来就是 aia_i=aia_i % aja_j; 这时候可以发现对aia_i的操作相当于求最大公约数的辗转相除,我们只需要求出来数组aa中元素的最大公约数, 设其为gcdagcd_a便是数组a操作后的最小数,再利用操作1,2让gcdagcd_a的倍数去覆盖包含的区间即可 对于每个数 ,包含的区间满足单调递增,符合二分性质,所以我们可以用二分来求解答案

    #include<bits/stdc++.h>
    using namespace std;
    int a[200005];
    int n,k;
    bool check(int x,int gcd)
    {
        int m=x/gcd;//当前数x所覆盖的区间
        if(m>n)
        m=n;//最大只能覆盖n个区间
        if(x>=k+m)//覆盖区间+k便是范围
        {
            return 1;
        }
        return 0;
    }
    int main()
    {
        int t;
        cin >> t;//相当于scanf
        while(t--)
        {
      
            cin >>n >>k;
            int gd=0;
            for(int i=1;i<=n;i++)
            {
                cin >> a[i];
            }
            if(n==1)//特判n==1的情况
            {
                if(k<=a[1])
                {
                    cout <<k-1<<'\n';
                }
                else
                cout<<k<<'\n';
                continue;
            }
            for(int i=1;i<=n;i++)
            {
                gd=__gcd(a[i],gd);
            }
            int ans=0;
            if(gd==1)//如果数组a的gcd等于1则填补区间为0-n-1;
            {
                cout <<n+k-1<<'\n';//相当于printf
            }
            else
            {
                    int l=1,r=n+k+10;//二分范围
                    int mid;
                    while(l<=r)
                    {
                        mid=(l+r)/2;
                        if(check(mid,gd))//如果满足条件 缩小
                        r=mid-1;
                        else//不满足条件,增大
                        l=mid+1;
                    }
                    cout <<l<<'\n';
    
            }
    
    
        }
    }
    
    • 1

    信息

    ID
    1014
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    21
    已通过
    1
    上传者