2 条题解

  • 0
    @ 2024-8-19 10:48:19

    分享一个用 gcd 做的方法,相对于正解来说时间复杂度会多带个 log,但是能过。

    思路

    假设一个数列 AA 能达到的最大公差为 GG,那么加入一个数字 mm 后新数列的最大公差显然是 gcd(G,abs(mAi))\gcd(G,abs(m-A_i)),其中 AiA_i 为数列中任意一个数字。(读者自证不难)

    特判一个数字的情况,然后从两个数字的情况初始化公差。

    若数列 AA 是等差数列,那么就肯定有 Amin+(lenA1)×G=AmaxA_{min}+(len_A-1)\times G=A_{max}

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

    代码

    #include <iostream>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    const int inf = 0x3f3f3f3f3f;
    int T,n,a[1001000],gc,tr[1001000],mx,mn,ans;
    int gcd(int a,int b){
    	if(!b)return a;
    	return gcd(b,a%b);
    }
    signed main(){
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d",&n);mx=0;mn=inf;ans=0;
    		for(int i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    			if(i==n)break;
    			mx=max(a[i],mx);mn=min(a[i],mn);
    			if(i==1){
    				tr[i]++;
    				continue;
    			}
    			if(i==2){
    				tr[i]++;
    				gc=mx-mn;
    				continue;
    			}
    			gc=gcd(gc,abs(a[i]-a[1]));
    			if(mn+(i-1)*gc==mx)tr[i]++;
    		}
    		mn=inf,mx=0;
    		for(int i=n;i>=1;i--){
    			if(i==1)break;
    			mx=max(a[i],mx);mn=min(a[i],mn);
    			if(i==n){
    				tr[i-1]++;
    				continue;
    			}
    			if(i==n-1){
    				tr[i-1]++;
    				gc=mx-mn;
    				continue;
    			}
    			gc=gcd(gc,abs(a[i]-a[n]));
    			if(mn+(n-i)*gc==mx)tr[i-1]++;
    		}
    		for(int i=1;i<n;i++){
    			if(tr[i]==2)ans++;
    			tr[i]=0;
    			
    		}
    		printf("%d\n",ans);
    	}
    	return 0;
    } 
    

    信息

    ID
    37
    时间
    1000ms
    内存
    512MiB
    难度
    3
    标签
    递交数
    368
    已通过
    103
    上传者