1 条题解

  • 0
    @ 2026-7-22 21:21:36

    Problem Link

    题目大意

    给定 a1ana_1\sim a_n,每次操作可以给 mm 个不同的 ai a_i 加一(在 modn\bmod n 意义下),求至少几次操作能让 aa 变成 0n10\sim n-1 的排列。

    数据范围:n2.5×105n\le 2.5\times 10^5

    思路分析

    考虑在不 modn\bmod n 意义下确定最终的 bib_i,要满足如下条件:

    • aibia_i\le b_i
    • bimodnb_i\bmod n 互不相同。
    • S=biaiS=\sum b_i-a_i,那么 mSm\mid S
    • max{biai}Sm\max \{b_i-a_i\}\le \dfrac Sm

    首先只有第一个条件和 bb 的相对顺序有关,为了满足这个条件,显然同时将 a,ba,b 升序排列最优。

    然后考虑第四个条件,对于一组合法解 b1bnb_1\sim b_n,如果 bnb1nb_n-b_1\ge n,那么调整 b1bnn,bnb1+nb_1\gets b_n-n,b_n\gets b_1+n

    显然不影响条件一、二、三的合法性,且此时 bnanb_n-a_n 会变小,且 b1a1=bna1n<bnanb'_1-a_1=b_n-a_1-n<b_n-a_n,因此 max{biai}\max\{b_i-a_i\} 也会变小。

    因此这样调整一定更优,最终一定有 bnb1<nb_n-b_1<n,即 bib_i 是连续的一段,存在一个 xx 使得 bi=x+i1b_i=x+i-1

    那么逐个满足条件即可,先找到 maxaii+1\max a_i-i+1,然后调整到最近的 xx 使得 n(2x+n1)2ai(modm)\dfrac{n(2x+n-1)}2\equiv \sum a_i\pmod m

    找到此时的 k=max{biai}k=\max\{b_i-a_i\},如果 k>Smk> \dfrac Sm,那么接下来就会进行若干次调整,每次会令 xx 加上 d=mgcd(n,m)d=\dfrac{m}{\gcd(n,m)}

    此时 kk 加上 mgcd(n,m)\dfrac m{\gcd(n,m)},且 Sm\dfrac Sm 加上 ngcd(n,m)\dfrac{n}{\gcd(n,m)},由于 n>mn>m 因此这个调整总能结束。

    时间复杂度 O(nlogn)\mathcal O(n\log n)

    代码呈现

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int MAXN=2.5e5+5;
    int n,m,a[MAXN],g;
    ll sum,k=0;
    signed main() {
    	scanf("%d%d",&n,&m),g=__gcd(n,m);
    	for(int i=0;i<n;++i) scanf("%d",&a[i]),sum+=a[i];
    	if((1ll*n*(n-1)/2-sum)%g) return puts("-1"),0;
    	sort(a,a+n);
    	for(int i=0;i<n;++i) k=max(k,(ll)a[i]-i);
    	sum=(2*k+n-1)*n/2-sum;
    	while(sum%m) ++k,sum+=n;
    	ll mx=0,d=m/__gcd(n,m),c=n*d/m;
    	for(int i=0;i<n;++i) mx=max(mx,k+i-a[i]);
    	if(mx>sum/m) {
    		ll cur=(mx-sum/m-1)/(c-d)+1;
    		printf("%lld\n",sum/m+cur*c);
    	} else printf("%lld\n",sum/m);
    	return 0;
    }
    
    • 1

    信息

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