codeforces#1549D. Integers Have Friends

D. Integers Have Friends

题意

给定数组\(A(a_1,a_2,a_3....a_n)\),求一个最大的连续子数组,子数组满足以下条件

  • \(m(m>1)\) 得到的余数相等

分析

假设子数组\((a_{i},a_{i+1},a_{i+2}....a_{j})\)​​​ 模\(m\)​​​都等于\(x\)​​​,那么它的差分数组\((a_{i+1}-a_{i},a_{i+2}-a_{i+1},a_{i+3}-a_{i+2}....a_j-a_{j-1})\)​​​模\(m\)​​都等于0

由此可以转化题目为,对于给定数组\(A\)的差分数组\(B(a_2-a_1,a_3-a_2,a_4-a_3.....a_n-a_{n-1})\)求最大公约数不为1的最长连续子数组。

我尝试使用线段树来求解,发现超出内存。改用倍增的方法,得到\(B\)中每个以\(l\)为起点长度为\(2^x\)​的子数组的最大公约数\(f[x][r]\)

注意到,求区间\([l,r]\)的最大公约数,可以变成求两区间\([l,a]\)\([b,r]\)的最大公约数,其中\(b\)满足\(l\leq b\leq (a+1)\)

AC代码

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define per(i,a,b) for (int i=(b);i>=(a);i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define SZ(x) ((int)(x).size())

typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> PII;

const ll mod=998244353 ;
const int maxn=2e5+7;
ll a[maxn],b[maxn],f[maxn][22];
int n;
ll _gcd(ll a,ll b){
    return b ? _gcd(b,a%b) : a;
}
ll check(int l,int r){
    int x=log2(r-l+1);
    return _gcd(f[l][x],f[r-(1<<x)+1][x]); 
}
int main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        rep(i,1,n){
            scanf("%lld",&a[i]);
        }
        rep(i,2,n){
            b[i-1]=abs(a[i]-a[i-1]);
            f[i-1][0]=b[i-1];
        }
        rep(i,1,20){
            rep(j,1,n-1){
                if(j+(1<<i)-1<=n-1)f[j][i]=_gcd(f[j][i-1],f[j+(1<<(i-1))][i-1]);
            }
        }
        int ans=1,l=1;
        rep(r,1,n-1){
            while(l<r&&check(l,r)==1)l++;
            if(check(l,r)!=1)ans=max(ans,r-l+2);
        }
        printf("%d\n",ans);
    }
    return 0;
}
posted @ 2021-08-07 10:37  czh~  阅读(53)  评论(0编辑  收藏  举报